今天说一说ListView的下拉刷新和上拉加载的初步实现,感觉自己写的东西基本上就是拾人牙慧,几乎没什么创新,就是把别人的东西东拼西凑来实现自己的需求。但是还是能学到点东西的,至少以后自己再遇到同样的请求可以看自己的总结就行了。
下拉刷新参考网址:android-Ultra-Pull-To-Refresh
上拉加载参考网址: ListView上拉加载更多的UI需求
先看一看效果
下拉刷新就不说了,下面说一说上拉加载实现的原理。
-
ListView 实现上拉加载更多,就是在ListView在滚动的时候,并且竖直方向上向上滚动的距离大于0,当最后一个 item 可见的时候触发加载更多的操作。请注意滚动 和 距离大于0 这两个条件,因为如果ListView 初始化的时候只有很少几项数据,这时候,最后item是可见的。这时候,ListView的滚动距离为0,所以不应该触发加载更多操作。
-
在加载更多的过程中,动态给ListView添加一个FootView,Footview有两种状态,正在加载,和没有更多数据。
-
在加载完成后,如果得到的数据不为空,就通知adapter notifyDataSetChanged() ,然后把FootView隐藏或者remove。如果得到的数据为空,FootView 就应该显示 no more data 类似的提示。
-
实现的步骤最主要的是给ListView添加一个滚动的监听事件,当ListView滚动的时候,判断是否满足加载更多的条件,如果满足,就加载更多。接下来看看自定义LsitView源码并不难理解
package com.example.listviewpulldownrefreshpulluploadmore;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
/**
* Created by dumingwei on 2016/8/20.
*/
public class MyListView extends ListView {
private boolean isPullUpLoading = false;//是否正在加载更多
private boolean noMoreItem = false;//是否还有更多数据
private LoadMoreListener loadMoreListener;//加载更多的回调接口
public void setNoMoreItem(boolean noMoreItem) {
this.noMoreItem = noMoreItem;
}
private PullUpLoadListViewFooter mFooterView;
public void setPullUpLoading(boolean pullUpLoading) {
isPullUpLoading = pullUpLoading;
}
public void setLoadMoreListener(LoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public MyListView(Context context) {
this(context, null);
}
public MyListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
isPullUpLoading = false;
mFooterView = new PullUpLoadListViewFooter(getContext());
setOnScrollListener(new MyOnScrollerListener());
}
private class MyOnScrollerListener implements OnScrollListener {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//do nothing here
}
/**
* Callback method to be invoked when the list or grid has been scrolled. This will be
* called after the scroll has completed
*
* @param view The view whose scroll state is being reported
* @param firstVisibleItem the index of the first visible cell (ignore if
* visibleItemCount == 0)
* @param visibleItemCount the number of visible cells
* @param totalItemCount the number of items in the list adaptor
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
/**
* 判断条件表示的意思
* !isPullUpLoading 不是处于正在加载更多的状态中
* !noMoreItem 还有更多数据
* (firstVisibleItem + visibleItemCount) == totalItemCount ,ListView的最后一个item可见
* getScrollDistance() > 0 ,ListView 向上滑动的距离大于0(如果不加这个条件,当ListView最初只有几项数据,以至于,前两个条件满足,会触发加载更多操作)
*/
if (!isPullUpLoading && !noMoreItem && (firstVisibleItem + visibleItemCount) == totalItemCount
&& getScrollDistance() > 0) {
showFootView();
if (loadMoreListener != null) {
loadMoreListener.loadMore();
}
}
}
}
/**
* 的到ListView 在竖直方向上的滑动距离
*
* @return
*/
public int getScrollDistance() {
View c = getChildAt(0);
if (c == null) {
return 0;
}
int firstVisiblePosition = getFirstVisiblePosition();
int top = c.getTop();
return -top + firstVisiblePosition * c.getHeight();
}
/**
* 加载更多的回调接口
*/
public interface LoadMoreListener {
void loadMore();
}
/**
* 显示footView
*/
public void showFootView() {
if (getFooterViewsCount() < 1) {
addFooterView(mFooterView);
}
mFooterView.setVisibility(View.VISIBLE);
mFooterView.updateView(PullUpLoadListViewFooter.State.LOADING);//显示Loading
}
/**
* 隐藏掉footView
*/
public void removeFootView() {
setPullUpLoading(false);
// removeFooterView(mFooterView);
mFooterView.setVisibility(View.GONE);
}
/**
* 数据已经完全加载完毕,footView 显示 no more
*/
public void haveLoadAll() {
setNoMoreItem(true);//没有更多数据
if (mFooterView != null) {
mFooterView.setVisibility(View.VISIBLE);
mFooterView.updateView(PullUpLoadListViewFooter.State.NOT_LOADING);//显示no more data
}
}
}
该说的都在注释里面了,使用的demo下载,请移步:ListViewPullDownRefreshPullUpLoadMore
2024.04.09 回顾,现在基本不用ListView了吧,都用RecyclerView了。