概述:
公司业务要求做一个横向滑动的,可以加载更多的控件。参考了郭霖大神关于下拉刷新的博客,地址为:http://blog.csdn.net/guolin_blog/article/details/9255575。在此基础上进行了改进,使之能适应横向加载更多的需求。横向滑动的控件采用的是RecyclerView,在外面包裹了本文介绍的控件。
思路:
控件继承自RelativeLayout,并重写dispatchTouchEvent()事件,当横向滑动的RecyclerView的右边缘滑动到控件的右边缘时,将隐藏的侧拉头跟随手势慢慢拉出。这中间伴随着侧拉头的状态实时的改变。松手时,如果侧拉的距离已经足够多,则回调onRefresh()方式。当回调结束时,需要手动停止刷新状态,让侧拉头再次隐藏。
好了,废话不多说,上代码:
package xxx;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import xxx.R;
/**
* 可进行左拉加载更多的自定义控件。
* 原理:1、当横向网格右边缘滑动到父控件右边缘时,让隐藏的侧拉头逐渐出现;
* 2、松手后,开始刷新;
* 3、完成后隐藏侧拉头
*
* @author jxl
*
*/
public class RefreshableView extends RelativeLayout {
private static final String TAG = "hello";
/**
* 左拉状态
*/
public static final int STATUS_PULL_TO_REFRESH = 0;
/**
* 释放立即刷新状态
*/
public static final int STATUS_RELEASE_TO_REFRESH = 1;
/**
* 正在刷新状态
*/
public static final int STATUS_REFRESHING = 2;
/**
* 刷新完成或未刷新状态
*/
public static final int STATUS_REFRESH_FINISHED = 3;
/**
* 左拉头部回滚的速度
*/
public static final int SCROLL_SPEED = -20;
/**
* 左拉加载更多的回调接口
*/
private PullToRefreshListener mListener;
/**
* 左拉头的View
*/
private View header;
/**
* 需要去左拉刷新的横置RecyclerView
*/
private RecyclerView refreshView;
/**
* 刷新时显示的进度条
*/
private ProgressBar progressBar;
/**
* 指示左拉和释放的箭头
*/
private ImageView arrow;
/**
* 左拉头的布局参数
*/
private LayoutParams headerLayoutParams;
/**
* 为了防止不同界面的左拉加载更多在上次更新时间上互相有冲突,使用id来做区分
*/
private int mId = -1;
/**
* 左拉头的宽度
*/
private int hideHeaderWidth;
/**
* 当前处理什么状态,可选值有STATUS_PULL_TO_REFRESH, STATUS_RELEASE_TO_REFRESH,
* STATUS_REFRESHING 和 STATUS_REFRESH_FINISHED
*/
private int currentStatus = STATUS_REFRESH_FINISHED;;
/**
* 记录上一次的状态是什么,避免进行重复操作
*/
private int lastStatus = currentStatus;
/**
* 手指按下时的屏幕横坐标
*/
private float xDown;
/**
* 在被判定为滚动之前用户手指可以移动的最大值。
*/
private int touchSlop;
/**
* 是否已加载过一次layout,这里onLayout中的初始化只需加载一次
*/
private boolean loadOnce;
/**
* 当前是否可以左拉,只有RecyclerView滚动到头的时候才允许左拉
*/
private boolean ableToPull;