swipRefreshLayout(下拉刷新)
swipRefreshLayou是v4包下的一个下拉刷新控件
1.setOnRefreshListener(OnRefreshListener listener)设置下拉监听,当用户下拉的时候会去执行回调
2.setColorSchemeColor(int…colors)设置进度条的颜色变化,最多可以设置4种颜色
3.setProgressViewOffset(boolean scale,int start,int end)调用进度条距离屏幕顶部的距离
4.setRefreshing(boolean refreshing)设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置true,在数据被加载到View中后,设置为false
注意swipRefreshLayou只能包含一个直接子view
SwipeRefreshLayout主要方法介绍
sRefreshing()
判断当前的状态是否是刷新状态
setColorSchemeResources(int… colorResIds)
设置下拉进度条的颜色主题,参数为可变参数,并且是资源id,可以设置多种不同的颜色,每转一圈就显示一种颜色。
setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)
设置监听,需要重写onRefresh()方法,顶部下拉时会调用这个方法,在里面实现请求数据的逻辑,设置下拉进度条消失等等。
setProgressBackgroundColorSchemeResource(int colorRes)
设置下拉进度条的背景颜色,默认白色。
setRefreshing(boolean refreshing)
设置刷新状态,true表示正在刷新,false表示取消刷新。
SwipeRefreshLayout的基本使用
1.设置布局
</android.support.v4.widget.SwipeRefreshLayout>
–>
2.在代码中使用
// 设置颜色属性的时候一定要注意是引用了资源文件还是直接设置16进制的颜色,因为都是int值容易搞混
// 设置下拉进度的背景颜色,默认就是白色的
swipeRefreshView.setProgressBackgroundColorSchemeResource(android.R.color.white);
// 设置下拉进度的主题颜色
swipeRefreshView.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary, R.color.colorPrimaryDark);
// 下拉时触发SwipeRefreshLayout的下拉动画,动画完毕之后就会回调这个方法
swipeRefreshView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// 开始刷新,设置当前为刷新状态
//swipeRefreshLayout.setRefreshing(true);
// 这里是主线程
// 一些比较耗时的操作,比如联网获取数据,需要放到子线程去执行
// TODO 获取数据
final Random random = new Random();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mList.add(0, "我是天才" + random.nextInt(100) + "号");
mAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, "刷新了一条数据", Toast.LENGTH_SHORT).show();
// 加载完数据设置为不刷新状态,将下拉进度收起来
swipeRefreshView.setRefreshing(false);
}
}, 1200);
// System.out.println(Thread.currentThread().getName());
// 这个不能写在外边,不然会直接收起来
//swipeRefreshLayout.setRefreshing(false);
}
});
自定义View继承SwipeRefreshLayout,添加上拉加载更多功能
1.获取子控件ListView
在布局使用中,这里和SwipeRefreshLayout一样,ListView是SwipeRefreshView的子控件,所以需要在onLayout()方法中获取子控件ListView。
// 获取ListView,设置ListView的布局位置
if (mListView == null) {
// 判断容器有多少个孩子
if (getChildCount() > 0) {
// 判断第一个孩子是不是ListView
if (getChildAt(0) instanceof ListView) {
// 创建ListView对象
mListView = (ListView) getChildAt(0);
// 设置ListView的滑动监听
setListViewOnScroll();
}
}
}
2.对ListView设置滑动监听
监听ListView的滑动事件,当滑动到底部,并且当前可见页的最后一个条目等于adapter的getCount数目-1,就满足加载数据的条件。
/**
- 设置ListView的滑动监听
*/
private void setListViewOnScroll() {
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 移动过程中判断时候能下拉加载更多
if (canLoadMore()) {
// 加载数据
loadData();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
}
3.处理SwipeRefreshView容器的分发事件
由于ListView是SwipeRefreshView的子控件,所以这里要进行事件的分发处理,判断用户的滑动距离是否满足条件。
/**
-
在分发事件的时候处理子控件的触摸事件
-
@param ev
-
@return
*/
private float mDownY, mUpY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 移动的起点
mDownY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
// 移动过程中判断时候能下拉加载更多
if (canLoadMore()) {
// 加载数据
loadData();
}
break;
case MotionEvent.ACTION_UP:
// 移动的终点
mUpY = getY();
break;
}
return super.dispatchTouchEvent(ev);
}
4.判断条件,满足就用回调去加载数据
当满足了需要判断的所有的条件之后,就可以去调用加载数据的方法,这里提供一个设置上拉布局显示和隐藏的方法,通过传入当前的状态,是true就显示加载,是false就隐藏。
/**
-
判断是否满足加载更多条件
-
@return
*/
private boolean canLoadMore() {
// 1. 是上拉状态
boolean condition1 = (mDownY - mUpY) >= mScaledTouchSlop;
if (condition1) {
System.out.println(“是上拉状态”);
}
// 2. 当前页面可见的item是最后一个条目
boolean condition2 = false;
if (mListView != null && mListView.getAdapter() != null) {
condition2 = mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - 1);
}
if (condition2) {
System.out.println("是最后一个条目");
}
// 3. 正在加载状态
boolean condition3 = !isLoading;
if (condition3) {
System.out.println("不是正在加载状态");
}
return condition1 && condition2 && condition3;
}
/**
- 处理加载数据的逻辑
*/
private void loadData() {
System.out.println(“加载数据…”);
if (mOnLoadListener != null) {
// 设置加载状态,让布局显示出来
setLoading(true);
mOnLoadListener.onLoad();
}
}
/**
-
设置加载状态,是否加载传入boolean值进行判断
-
@param loading
*/
public void setLoading(boolean loading) {
// 修改当前的状态
isLoading = loading;
if (isLoading) {
// 显示布局
mListView.addFooterView(mFooterView);
} else {
// 隐藏布局
mListView.removeFooterView(mFooterView);// 重置滑动的坐标 mDownY = 0; mUpY = 0;
}
}