您的位置:首页 > 移动开发 > Android开发

android下拉刷新之PullToRefreshListView(二)

2015-07-19 11:20 721 查看
在上一次的实现下拉刷新中android下拉刷新之PullToRefreshListView(一),我使用开源的代码PullToRefreshListView实现了比较基础的上拉刷新、下拉刷新,但是在写完之后结合我们在实际使用,还发现了一些需要我们可以灵活配置,但是上一次还没有实现的,那么这一次,我就准备通过阅读其源码来查看其是否支持,以及其实现的原理

上次留下的几个问题有:

1、还没有完成下拉刷新和上拉刷新时的动画及文字的自定义

2、虽然有了上拉到显示最后一项时,立刻加载下一页的功能,但是如果再进行需求的灵活变通时,就

存在一定的局限性,例如在显示到倒数第五个时就加载下一页,这样在网速没有问题时可以让用户毫无阻力地显示下一页

一、下拉刷新动画能否灵活定制

那么第一步就是针对下拉刷新时动画的自定义

首先我们先找到PullToRefreshListView这个类,由于我只是需要找我需要的关键部分,所以就不对每一个方法进行分析,在这里先找它所有公开的方法:

这个方法可以发现是返回一个拉动刷新的方向,返回值只有纵向和横向两个值,可见可以支持两种方向的拉动刷新
@Override
	public final Orientation getPullToRefreshScrollDirection() {
		return Orientation.VERTICAL;
	}
PullToRefreshListView这个类中的公开方法就这一个,可见其他方法应该在其父类中,那么就去其父类中去寻找

可以发现以下方法:

public boolean getShowIndicator()

public void setAdapter(ListAdapter adapter)

public final void setEmptyView(View newEmptyView)

public void setOnItemClickListener(OnItemClickListener listener)

public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener)

public final void setOnScrollListener(OnScrollListener listener)

public final void setScrollEmptyView(boolean doScroll)

public void setShowIndicator(boolean showIndicator)


其中很多方法对我们是没有用的,比如
setShowIndicator(boolean showIndicator)


这一句是指是否要设置在拉动时的一个图标,在实际项目中意义不大,而剔除不需要的方法之后,针对我之前所需要实现的需求的方法就是这个

public final void setOnScrollListener(OnScrollListener listener)
这个方法是监听上下滑动的,这里应该可以实现监听距离最后几项时加载下一页,这里先做好标记,因为现在需要的是定制刷新时的视图

然后在这个类里面也没找到我们需要的跟设置下拉刷新时视图设置有关的,那么就继续找它的父类PullToRefreshBase

在这个类里面,终于找到了我需要的两个方法

/**
	 * Returns a proxy object which allows you to call methods on all of the
	 * LoadingLayouts (the Views which show when Pulling/Refreshing).
	 * <p />
	 * You should not keep the result of this method any longer than you need
	 * it.
	 * 
	 * @return Object which will proxy any calls you make on it, to all of the
	 *         LoadingLayouts.
	 */
	public ILoadingLayout getLoadingLayoutProxy();

	/**
	 * Returns a proxy object which allows you to call methods on the
	 * LoadingLayouts (the Views which show when Pulling/Refreshing). The actual
	 * LoadingLayout(s) which will be affected, are chosen by the parameters you
	 * give.
	 * <p />
	 * You should not keep the result of this method any longer than you need
	 * it.
	 * 
	 * @param includeStart - Whether to include the Start/Header Views
	 * @param includeEnd - Whether to include the End/Footer Views
	 * @return Object which will proxy any calls you make on it, to the
	 *         LoadingLayouts included.
	 */
	public ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd)


可以看到,第两个方法都是获取加载的布局,然后可以在获取到的布局对象内修改一下显示的数据

public ILoadingLayout getLoadingLayoutProxy();
这个方法获取后修改了数据的话上拉和下拉会同时改变

public ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd)
这个方法则是可以上拉和下拉设置不同的文字和图片

那么,让我们去看看这个ILoadingLayout 有哪些属性可以让我们灵活配置

public interface ILoadingLayout {

	/**
	 * Set the Last Updated Text. This displayed under the main label when
	 * Pulling
	 * 
	 * @param label - Label to set
	 */
<span style="white-space:pre">	</span>这个方法用于设置最后一次更新的时间
	public void setLastUpdatedLabel(CharSequence label);

	/**
	 * Set the drawable used in the loading layout. This is the same as calling
	 * <code>setLoadingDrawable(drawable, Mode.BOTH)</code>
	 * 
	 * @param drawable - Drawable to display
	 */
<span style="white-space:pre">	</span>这个方法用于返回加载时的图片
	public void setLoadingDrawable(Drawable drawable);

	/**
	 * Set Text to show when the Widget is being Pulled
	 * <code>setPullLabel(releaseLabel, Mode.BOTH)</code>
	 * 
	 * @param pullLabel - CharSequence to display
	 */
<span style="white-space:pre">	</span>拉动时的文字
	public void setPullLabel(CharSequence pullLabel);

	/**
	 * Set Text to show when the Widget is refreshing
	 * <code>setRefreshingLabel(releaseLabel, Mode.BOTH)</code>
	 * 
	 * @param refreshingLabel - CharSequence to display
	 */
<span style="white-space:pre">	</span>刷新时的文字
	public void setRefreshingLabel(CharSequence refreshingLabel);

	/**
	 * Set Text to show when the Widget is being pulled, and will refresh when
	 * released. This is the same as calling
	 * <code>setReleaseLabel(releaseLabel, Mode.BOTH)</code>
	 * 
	 * @param releaseLabel - CharSequence to display
	 */
<span style="white-space:pre">	</span>下拉到可以放手刷新时的文字
public void setReleaseLabel(CharSequence releaseLabel);

	/**
	 * Set's the Sets the typeface and style in which the text should be
	 * displayed. Please see
	 * {@link android.widget.TextView#setTypeface(Typeface)
	 * TextView#setTypeface(Typeface)}.
	 */
<span style="white-space:pre">	</span>设置文字的样式及字体
	public void setTextTypeface(Typeface tf);

}


那么到了这里,就基本可以知道如何设置下拉时的文字以及图片了

ILoadingLayout startLabels = mPullRefreshListView  
                .getLoadingLayoutProxy();  
        startLabels.setPullLabel("正在下拉...");// 刚下拉时,显示的提示  
        startLabels.setRefreshingLabel("正在刷新...");// 刷新时  
        startLabels.setReleaseLabel("现在放手就可刷新...");// 下拉达到一定距离时,显示的提示


那么,这是按照这个代码内置的布局来展示的刷新的样式,如果我们希望可以自己定义刷新的样式呢?

这是一个接口,那么我们就需要找返回实现这个接口的地方,只要将其实现的地方,找到其布局,进行一番修改即可,同时也可以在其中写一个自己需要的布局,继承一下其接口,然后在

public ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd)
这个方法中返回,就可以达到配置不同布局的效果

我本身的话还有一个需求,就是,现在的这个代码,我会发现我可以下拉刷新的拉动的高度貌似过高,所以,我希望我可以设定我能拉出来的高度

预留

针对下拉刷新的部分我后来的确找到了设置下拉的高度的地方,就在



PullToRefreshBase这个类的pullEvent()方法中,然而这个方法是私有的,并不开放给用户来设置,在其中,实时计算下拉的高度来设置显示出下拉的高度,但是没有设置上限,所以会导致不断拉则headView不断变高

在这个方法中setHeaderScroll(int)这个方法用于控制拉动时的view的高度,但是刷新时的高度却不会影响,这里应该是需要在布局上进行设置一下



二、显示到我指定的倒数项时能让我知道

这一点在我之前看源码时就发现了可以设置的地方

mListView.setOnScrollListener(new OnScrollListener() {
			
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				Log.i("ceshi","现在正在改变1:" + scrollState);
//				scrollState == OnScrollListener.SCROLL_STATE_IDLE	表示滚动到底部
			}
			
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				Log.i("ceshi","现在正在改变w:" + firstVisibleItem + ",可见的数字:" + visibleItemCount + ",总共有:" + totalItemCount);
				//这里的规则是:firstVisibleItem当前显示的第一个是第多少项
				//visibleItemCount可见的有多少项
				//totalItemCount总共有多少项
				//当滑动到底部时   totalItemCount = firstVisibleItem + visibleItemCount
				//所以如果想在滑动到还有五项就到底时就加载下一页的话就是
				if((firstVisibleItem + visibleItemCount + 5)>=totalItemCount){
					//加载下一页
					Log.i("ceshi", "满足加载下一页了");
					//现在这种处理方式如果不加一个防止反复加载下一页的机制的话会出现问题
				}
				
			}
		});


综合一下,对于我目前想到的一些情况基本可以满足,只是可能在满足非下拉时整体布局向下滑动的情况时就需要对源码进行一定的修改,只是,由于整体逻辑比较复杂,注释又比较少,所以如果出了什么少见的问题在解决时会比较麻烦

在网上现成的比较优秀的工具使用研究过后,下一步我将找时间尝试自己写一个下拉刷新,以便深入了解下拉刷新这个功能的实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: