RecyclerView上拉加载更多功能回弹实现

来源:互联网 发布:淘宝出售假冒申诉材料 编辑:程序博客网 时间:2024/06/05 06:01

部分代码参考http://blog.csdn.net/dalancon/article/details/46125667


实现原理是使用RecyclerView的OnTouchListener方法监听滑动 在adapter里面增加两项footview 其中date.size为显示的加载条,可以自定义,date.size+1为空白的View,我们设置其高度为0 我们通过LinearLayoutManager的 findLastVisibleItemPosition判断显示的最后一条数据,如果是空白view,表示加载条已经完全展示,松开即可刷新。

回弹效果是通过在滑动时动态改变空白view的高度,达到阻尼效果 ,回弹时再动态将其改为0,达到回弹效果,通过loading防止加载过程中滑动导致显示问题 这里的回调采用了Runnable传参

public class RefreshFootAdapter extendsRecyclerView.Adapter<RecyclerView.ViewHolder> {// 上拉加载更多public static final int SATUS_PULLUP_LOAD_MORE = 0;// 正在加载中public static final int SATUS_LOADING_MORE = 1;public static final int SATUS_UP_LOADING_MORE = 2;// 上拉加载更多状态-默认为0private int load_more_status = 0;private LayoutInflater mInflater;private List<String> mTitles = null;private static final int TYPE_ITEM = 0; // 普通Item Viewprivate static final int TYPE_FOOTER = 1; // 底部FootViewprivate static final int TYPE_FOOTER_EMPTY = 2; // 底部空白Viewprivate static int pagesize;private int eview_height = 1;private long TimeFlag;// 回弹时间private RecyclerView parent;private boolean loadmare;// 判断当前是可加载更多private boolean loading;// 判断是否正在加载private int startY, nowY;// 滑动判断//构造函数 处理滑动监听 更新等功能public RefreshFootAdapter(Context context, RecyclerView parent,final LinearLayoutManager linearLayoutManager, int pagesize,final Runnable onloadmore) {this.parent = parent;this.mInflater = LayoutInflater.from(context);this.mTitles = new ArrayList<String>();for (int i = 0; i < 20; i++) {int index = i + 1;mTitles.add("item" + index);}this.pagesize = pagesize;parent.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent ev) {// TODO Auto-generated method stubswitch (ev.getAction()) {case MotionEvent.ACTION_MOVE:nowY = (int) ev.getY();if (RefreshFootAdapter.this.getItemCount() == linearLayoutManager.findLastVisibleItemPosition() + 1) {if (startY == 0) {// 按下startY = nowY;}int changeY = nowY - startY;RefreshFootAdapter.this.notifyEmptyView((int) (-changeY / 1.3f));if (loading) {return false;}RefreshFootAdapter.this.changeMoreStatus(RefreshFootAdapter.this.SATUS_UP_LOADING_MORE);loadmare = true;} else {loadmare = false;if (loading) {return false;}RefreshFootAdapter.this.changeMoreStatus(RefreshFootAdapter.this.SATUS_PULLUP_LOAD_MORE);// 普通的滑动startY = 0;}break;case MotionEvent.ACTION_UP:RefreshFootAdapter.this.resetEmptyView();if (loadmare) {if (loading) {return false;} else {RefreshFootAdapter.this.changeMoreStatus(RefreshFootAdapter.this.SATUS_LOADING_MORE);if (onloadmore != null && !loading) {loading = true;onloadmore.run();}}}startY = 0;break;default:break;}return false;}});}/** * item显示类型 *  * @param parent * @param viewType * @return */public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {// 进行判断显示类型,来创建返回不同的Viewif (viewType == TYPE_ITEM) {View view = mInflater.inflate(R.layout.item_recycler_layout,parent, false);// 这边可以做一些属性设置,甚至事件监听绑定// view.setBackgroundColor(Color.RED);ItemViewHolder itemViewHolder = new ItemViewHolder(view);return itemViewHolder;} else if (viewType == TYPE_FOOTER) {View foot_view = mInflater.inflate(R.layout.recycler_load_more_layout, parent, false);// 这边可以做一些属性设置,甚至事件监听绑定// view.setBackgroundColor(Color.RED);FootViewHolder footViewHolder = new FootViewHolder(foot_view);return footViewHolder;} else if (viewType == TYPE_FOOTER_EMPTY) {View foot_view_empty = mInflater.inflate(R.layout.recycler_load_more_layout_empty, parent, false);// 这边可以做一些属性设置,甚至事件监听绑定// view.setBackgroundColor(Color.RED);FootEmptyHolder footEmptyViewHolder = new FootEmptyHolder(foot_view_empty);return footEmptyViewHolder;}return null;}/** * 数据的绑定显示 *  * @param holder * @param position */public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {if (holder instanceof ItemViewHolder) {((ItemViewHolder) holder).item_tv.setText(mTitles.get(position));holder.itemView.setTag(position);} else if (holder instanceof FootViewHolder) {FootViewHolder footViewHolder = (FootViewHolder) holder;switch (load_more_status) {case SATUS_PULLUP_LOAD_MORE:footViewHolder.foot_view_item_tv.setText("上拉加载更多...");break;case SATUS_LOADING_MORE:footViewHolder.foot_view_item_tv.setText("正在加载更多数据...");break;case SATUS_UP_LOADING_MORE:footViewHolder.foot_view_item_tv.setText("松开加载更多数据...");break;}} else if (holder instanceof FootEmptyHolder) {FootEmptyHolder footViewHolder = (FootEmptyHolder) holder;footViewHolder.empty.setLayoutParams(new ViewGroup.LayoutParams(111, eview_height));}}/** * 进行判断是普通Item视图还是FootView视图 *  * @param position * @return */@Overridepublic int getItemViewType(int position) {// 最后一个item设置为footerViewif (position + 1 == getItemCount()) {return TYPE_FOOTER_EMPTY;} else if (position + 2 == getItemCount()) {return TYPE_FOOTER;} else {return TYPE_ITEM;}}//如果是页数的倍数 itemcount+2@Overridepublic int getItemCount() {if (mTitles.size() % pagesize != 0) {return mTitles.size();} else {return mTitles.size() + 2;}// return mTitles.size()+1;}// 自定义的ViewHolder,持有每个Item的的所有界面元素public static class ItemViewHolder extends RecyclerView.ViewHolder {public TextView item_tv;public ItemViewHolder(View view) {super(view);item_tv = (TextView) view.findViewById(R.id.item_tv);}}/** * 底部FootView布局 */public static class FootViewHolder extends RecyclerView.ViewHolder {private TextView foot_view_item_tv;public FootViewHolder(View view) {super(view);foot_view_item_tv = (TextView) view.findViewById(R.id.foot_view_item_tv);}}//空白项public static class FootEmptyHolder extends RecyclerView.ViewHolder {private View empty;public FootEmptyHolder(View view) {super(view);empty = view.findViewById(R.id.empty);}}// 添加数据public void addItem(List<String> newDatas) {// mTitles.add(position, data);// notifyItemInserted(position);newDatas.addAll(mTitles);mTitles.removeAll(mTitles);mTitles.addAll(newDatas);notifyDataSetChanged();}//更新添加数据public void addMoreItem(List<String> newDatas) {mTitles.addAll(newDatas);notifyDataSetChanged();}//更新空白项高度private void notifyEmptyView(int height) {this.eview_height = height;notifyItemChanged(getItemCount() - 1);}//空白回弹 伪回弹动画private void resetEmptyView() {final int dx = eview_height;new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubfinal int time = 500;final long startTime = new Date().getTime();TimeFlag = startTime;long nowTime = new Date().getTime();while (startTime + time > nowTime && TimeFlag == startTime) {nowTime = new Date().getTime();final int dt = (int) (nowTime - startTime);parent.post(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubeview_height = eview_height * (time - dt) / time;notifyDataSetChanged();}});try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}parent.post(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubeview_height = 0;notifyDataSetChanged();}});}}).start();}//停止加载更多 重置loading状态和显示文本public void stopLoadMore() {notifyDataSetChanged();loading = false;RefreshFootAdapter.this.changeMoreStatus(RefreshFootAdapter.this.SATUS_PULLUP_LOAD_MORE);}//改变加载条状态private void changeMoreStatus(int status) {if (loading) {return;}load_more_status = status;notifyDataSetChanged();}}

图1为滑动过程

图2为松开加载

0 0
原创粉丝点击