加载下拉刷新"/>
通过SwipeRefreshLayout实现ListView的上拉加载下拉刷新
上拉刷新下拉加载相信是在日常的开发中使用的最频繁的一个组件了,大量数据的展示一定会使用到分页的功能以提升用户体验,目前可以看到的市面上的应用的下拉刷新也都是配合的SwipeRefreshLayout来实现的,看起来比较美观,相比自定义的下拉刷新的动画效果,这个就显得比较简洁大方了。
下面看一下运行效果:
由于ListView没有提供默认的分页加载的功能,因此这里就需要我们自定了,实现起来也是比较简单的,大致的思路就是:给ListView添加一个FootView用来显示正在加载的等待动画,以及滑动到listview最底部的Item的监听,然后通过回调将事件的处理交给外部进行。
LoadListView.Java
/*** Created by 春水碧于天 on 2017/1/29.*/public class LoadListView extends ListView implements AbsListView.OnScrollListener {private int mFootViewHeight;private View mFootView;private int LOADSTATE = 0; //加载的状态public LoadListView(Context context) {super(context);InitFootView(context);setOnScrollListener(this);}public LoadListView(Context context, AttributeSet attrs) {super(context, attrs);//初始化脚布局并添加到当前的ListViewInitFootView(context);setOnScrollListener(this);}public LoadListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}private void InitFootView(Context context) {mFootView = View.inflate(context, R.layout.foot_load_item, null);mFootView.measure(0, 0); //测量mFootViewHeight = mFootView.getMeasuredWidth();addFooterView(mFootView);}//加载完成调用隐藏脚布局,并把mLoadState的状态设置为0,表示未刷新状态public void setLoadComplete() {LOADSTATE = 0;//加载完成后隐藏脚布局mFootView.setPadding(0, -mFootViewHeight, 0, 0);}//滑动状态改变的监听@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {}/*** 滑动时一直调用* @param view* @param firstVisibleItem 当前能看见的第一条item的Id* @param visibleItemCount 当前能看见的item的总数* @param totalItemCount 所有的item*/@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {Log.i("wk","firstVisibleItem: "+firstVisibleItem+"visibleItemCount: "+visibleItemCount+"totalItemCount: "+totalItemCount);//判断是否滑动到当前listview的最后一个条目if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {if (LOADSTATE == 0) {//取消隐藏mFootView.setPadding(0, 0, 0, 0);onLoadListener.onLoading();LOADSTATE = 1; //设置状态为加载中,放置多次调用onLoading}}}//加载更多的回调接口private OnLoadListener onLoadListener;public void setOnLoadlistener(OnLoadListener onLoadListener) {this.onLoadListener = onLoadListener;}public interface OnLoadListener {void onLoading();}
}
这里记录一下OnScrollListener中的两个回调方法的作用:
1.onScrollStateChanged
//滑动状态改变的监听@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {switch (scrollState) {//根据手指离开后的惯性滑动时调用case OnScrollListener.SCROLL_STATE_FLING:Log.i("wk","惯性滑动");break;//滚动停止时调用case OnScrollListener.SCROLL_STATE_IDLE:Log.i("wk","滚动停止");break;//正在滚动时调用case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:Log.i("wk","正在滚动");break;}}
这个方法根据第二个参数 scrollState 来决定回调的次数
2.onScroll
/*** 滑动时一直调用** @param view* @param firstVisibleItem 当前能看见的第一条item的Id* @param visibleItemCount 当前能看见的item的总数* @param totalItemCount 所有的item*/
@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}
它在ListView滑动时一直调用,通过onScroll中的三个参数,非常精确的描述了ListView的当前状态
firstVisibleItem 当前能看见的第一条item的Position
visibleItemCount 当前能看见的item的总数(包括没有完全显示的条目)
totalItemCount 所有的item
判断显示到了最后一行:
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {}
判断ListView滑动的方向:
private int lastVisibleItem = 0;@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {Log.i("wk","lastVisibleItem=> "+lastVisibleItem+"firstVisibleItem=> "+firstVisibleItem);if(lastVisibleItem>firstVisibleItem){Log.i("wk","下滑");}else if (lastVisibleItem<firstVisibleItem){Log.i("wk","上滑");}lastVisibleItem = firstVisibleItem;
foot_load_item.Java
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=""android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:orientation="horizontal"><ProgressBar
android:layout_margin="10dp"android:layout_width="50dp"android:layout_height="50dp"/>
<TextView
android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="正在加载中……"android:layout_margin="10dp"android:textSize="20dp"android:layout_gravity="center"/></LinearLayout>
这样一个支持上拉加载更多的ListView就实现了。
下面通过配合SwipeRefreshLayout来实现下拉刷新:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=""xmlns:tools=""android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.studyslide.MainActivity">
<android.support.v4.widget.SwipeRefreshLayoutandroid:id="@+id/swipeRefreshLayout"android:layout_width="match_parent"android:layout_height="match_parent"><com.example.studyslide.LoadListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="match_parent"></com.example.studyslide.LoadListView></android.support.v4.widget.SwipeRefreshLayout></LinearLayout>
MainActivity.Java
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {private LoadListView mListView;private ArrayList<String> mDatas;private SwipeRefreshLayout swipeRefreshLayout;private Handler mHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);InitData();InitUI();//设置加载显示的颜色,可以设置显示多种颜色swipeRefreshLayout.setColorSchemeColors(Color.BLUE, Color.RED, Color.GREEN, Color.GRAY);//设置swipeRefreshLayout的背景颜色//swipeRefreshLayout.setBackgroundColor(Color.CYAN);//设置显示的大小swipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE);
/*//设置手指下拉多少出现刷新swipeRefreshLayout.setDistanceToTriggerSync(200);//设置刷新出现的位置swipeRefreshLayout.setProgressViewEndTarget(false,200);*///设置刷新的监听swipeRefreshLayout.setOnRefreshListener(this);final myAdapter myAdapter = new myAdapter();/*** 模拟网络数据加载*/mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);int tag = msg.what;switch (tag) {//刷新case 0:for (int i = 0; i < 10; i++) {mDatas.add(0, "刷新出的数据" + i);}swipeRefreshLayout.setRefreshing(false);myAdapter.notifyDataSetChanged();break;//加载更多case 1:for (int i = 0; i < 10; i++) {mDatas.add("加载出的数据" + i);}mListView.setLoadComplete();myAdapter.notifyDataSetChanged();break;}}};mListView.setAdapter(myAdapter);mListView.setOnLoadlistener(new LoadListView.OnLoadListener() {@Overridepublic void onLoading() {Toast.makeText(MainActivity.this, "加载更多", Toast.LENGTH_SHORT).show();//模拟网络加载数据延迟new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(2000);mHandler.sendEmptyMessage(1);} catch (InterruptedException e) {e.printStackTrace();} finally {}}}).start();}});}private void InitUI() {mListView = (LoadListView) findViewById(R.id.listView);swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);}private void InitData() {mDatas = new ArrayList<String>();for (int i = 0; i < 40; i++) {mDatas.add("这是" + i + "条数据");}}@Overridepublic void onRefresh() {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(2000);mHandler.sendEmptyMessage(0);} catch (InterruptedException e) {e.printStackTrace();} finally {}}}).start();}//ListView的适配器class myAdapter extends BaseAdapter {@Overridepublic int getCount() {return mDatas.size();}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder = null;if (convertView == null) {viewHolder = new ViewHolder();convertView = View.inflate(MainActivity.this, R.layout.item_listview, null);viewHolder.tv = (TextView) convertView.findViewById(R.id.textView);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}viewHolder.tv.setText(mDatas.get(position));return convertView;}final class ViewHolder {public TextView tv;}}}
下面记录一下SwipeRefreshLayout的使用:
常用的方法:
setOnRefreshListener(this):添加一个刷新的监听
setRefreshing(): 显示或隐藏刷新进度条
isRefreshing(): 检查当前是否处于刷新状态
setColorScheme(): 设置进度条的颜色主题,最多能设置四种
swipeRefreshLayout.setBackgroundColor():设置SwipeRefreshLayout 的背景色
swipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE):设置刷新控件显示大小,默认为small
swipeRefreshLayout.setDistanceToTriggerSync(200):设置手指下拉多少出现刷新
swipeRefreshLayout.setProgressViewEndTarget(false,200):设置刷新出现的位置
这样一个可以上拉加载下拉刷新的ListView就完成了,呵呵,比较朴素的效果实现。
更多推荐
通过SwipeRefreshLayout实现ListView的上拉加载下拉刷新
发布评论