自定义的RecyclerView, 下拉刷新,加载更多.
来源:互联网 发布:宋太祖宋真宗去世知乎 编辑:程序博客网 时间:2024/05/22 15:01
编写用到的下拉刷新的布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#f00" android:gravity="center" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/ll" > <TextView android:id="@+id/status" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="显示一些东西" android:textColor="#000" /> </LinearLayout></LinearLayout>
自定义RecyclerView 封装了下拉刷新和加载更多的功能
/** * 下拉刷新和加载更多的 自定View * Created by SwmIsMe on 2017/3/2. */public class MyRecyclerView extends RecyclerView { public final static int STATE_NORMAL = 0; public final static int STATE_READY = 1; public final static int STATE_REFRESHING = 2; MyLoadRefreshAdapter mLoadRefreshAdapter; View headerView, footerView; private int mState = STATE_NORMAL; // 头布局的高度 int headerViewHeight; // 是否正在触摸 boolean isOnTouching; TextView status; boolean isRefresh; private LinearLayout mLl; private LinearLayout.LayoutParams mParams; private LayoutManager mLayoutManager; public MyRecyclerViewListener getMyRecyclerViewListener() { return myRecyclerViewListener; } // 设置 监听 public void setMyRecyclerViewListener(MyRecyclerViewListener myRecyclerViewListener) { this.myRecyclerViewListener = myRecyclerViewListener; } MyRecyclerViewListener myRecyclerViewListener; public MyRecyclerView(Context context) { super(context); } public MyRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } int lastX, lastY; @Override public boolean onTouchEvent(MotionEvent e) { int x = (int) e.getX(); int y = (int) e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: isOnTouching = true;// 获取到 轮播的view View view1 = this.getChildAt(1);// 获取到 轮播的view安排的位置. int loopViewPagerPosition = this.getChildLayoutPosition(view1);// 如果 轮播的view安排(layout)的位置. 是第一个 触发下拉刷新的操作. if (loopViewPagerPosition == 1) { if (lastY == 0) { lastY = y; } int dy = lastY - y; int dx = lastX - x; int yabs = Math.abs(dy); int xabs = Math.abs(dx); if (yabs > xabs) { isRefresh = true; changeHeight(dy); this.requestDisallowInterceptTouchEvent(true); } else { this.requestDisallowInterceptTouchEvent(false); } lastX = x; lastY = y; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: isRefresh = false; isOnTouching = false;// 归零 lastY = 0;// 开始刷新 if (mState == STATE_READY || mState == STATE_REFRESHING) { onStatusChange(STATE_REFRESHING); autoSize(0); }// 回归到 隐藏的位置 if (mState == STATE_NORMAL) { autoSize(-headerViewHeight); } break; } return super.onTouchEvent(e); } // 通过改变 topMargin的值.改变高度 private void changeHeight(int dy) { mParams.topMargin -= dy; int margin = mParams.topMargin; mLl.setLayoutParams(mParams); setStateByHeight(margin, false); } /** * 更新 头布局的高度 * * @param targetHeight 要改变到的高度 当这个高度为0时,topMargin为0,显示整个刷新的界面, * -headerViewHeight 隐藏头布局 */ public void autoSize(int targetHeight) { int currentHeight = mParams.topMargin;// 从当前高度 到 目前高度,的动画变化值. ValueAnimator objectAnimator = ValueAnimator.ofInt(currentHeight, targetHeight);// 设置下拉刷新的高度 objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int animatedValue = (int) animation.getAnimatedValue();// 根据高度设置文本 setStateByHeight(animatedValue, true); mParams.topMargin = animatedValue; mLl.setLayoutParams(mParams); } }); objectAnimator.start(); } // 设置加载更多的判断 @Override public void setLayoutManager(final LayoutManager layout) { super.setLayoutManager(layout); this.addOnScrollListener(new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (isRefresh) { return; } if (mState != STATE_NORMAL) { return; } LogUtils.e("new state" + newState); //判断是否最后一item个显示出来 mLayoutManager = getLayoutManager(); //可见的item个数 int visibleChildCount = mLayoutManager.getChildCount();// 如果大于0 并且 状态不等于空闲 并且 没有在加载更多 if (visibleChildCount > 0 && newState == RecyclerView.SCROLL_STATE_IDLE && !isLoadMore) {// 获取最后一个 view 除加载更多view View lastVisibleView = recyclerView.getChildAt(recyclerView.getChildCount() - 1);// 返回给定子视图的适配器位置 int lastVisiblePosition = recyclerView.getChildLayoutPosition(lastVisibleView);// 如果 最后一个可见的位置 大于等于 if (lastVisiblePosition >= mLayoutManager.getItemCount() - 1) {// 加载更多view 可见 footerView.setVisibility(VISIBLE); isLoadMore = true;// 加载更多 if (myRecyclerViewListener != null) { myRecyclerViewListener.onLoadMore(); } } else { footerView.setVisibility(GONE); } } } }); } // 根据高度来设置 现在的状态 private void setStateByHeight(int height, boolean isAuto) { if (mState == STATE_REFRESHING) { return; }// 如果 当前的高度 小于 头布局的高度 if (height < headerViewHeight) { onStatusChange(STATE_NORMAL); } else if (height > headerViewHeight) { onStatusChange(STATE_READY); } else if (height == headerViewHeight && !isOnTouching && !isAuto) { onStatusChange(STATE_REFRESHING); } } boolean isLoadMore; public void onStatusChange(int status) { mState = status; switch (status) { case STATE_READY: this.status.setText("松开刷新..."); break; case STATE_NORMAL: this.status.setText("下拉刷新..."); break; case STATE_REFRESHING: this.status.setText("正在刷新..."); if (myRecyclerViewListener != null) { myRecyclerViewListener.onRefresh(); } break; } } // 初始化头尾布局 和 头尾view的适配器 @Override public void setAdapter(Adapter adapter) { ArrayList<View> headers = new ArrayList<>(); ArrayList<View> footers = new ArrayList<>();// 加载下拉刷新的布局文件 View refreshView = LayoutInflater.from(getContext()).inflate(R.layout.item_recycler_refresh, null); headerView = refreshView; status = (TextView) refreshView.findViewById(R.id.status); mLl = (LinearLayout) refreshView.findViewById(R.id.ll); headerView.post(new Runnable() { @Override public void run() {// 头布局真正的高度 headerViewHeight = headerView.getHeight();// 设置layout参数 隐藏头布局 mParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); mParams.topMargin = -headerViewHeight; mParams.width = ScreenUtils.screenW; mLl.setLayoutParams(mParams); } });// 将头布局添加到 集合中 headers.add(headerView);// 初始化 尾布局 LinearLayout footerLayout = new LinearLayout(getContext()); footerLayout.setGravity(Gravity.CENTER); footerLayout.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); footers.add(footerLayout); footerLayout.setPadding(0, 15, 0, 15); footerLayout.addView(new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmall)); TextView text = new TextView(getContext()); text.setText("正在加载..."); footerLayout.addView(text); footerView = footerLayout; footerView.setVisibility(GONE);// 初始化 适配器 mLoadRefreshAdapter = new MyLoadRefreshAdapter(adapter, headers, footers); super.setAdapter(mLoadRefreshAdapter); } public interface MyRecyclerViewListener { void onRefresh(); void onLoadMore(); } // 完成加载更多 public void setLoadMoreComplete() {// 直接隐藏 尾布局 footerView.setVisibility(GONE); isLoadMore = false; } // 完成下拉刷新 public void setRefreshComplete() { onStatusChange(STATE_NORMAL); autoSize(-headerViewHeight); }}
自定义 MyLoadRefreshAdapter 适配器
/** * 实现显示头部和尾部item的adapter,把头部尾部的事情交给这个adapter来做,其他的交给子adapter * Created by SwmIsMe on 2017/3/2. */public class MyLoadRefreshAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public ArrayList<View> headerViews = new ArrayList<>(); public ArrayList<View> footViews = new ArrayList<>(); public RecyclerView.Adapter adapter; public MyLoadRefreshAdapter(RecyclerView.Adapter adapter, ArrayList<View> headerViews, ArrayList footViews) { this.adapter = adapter; this.headerViews = headerViews; this.footViews = footViews; } MyLoadRefreshListener mLoadRefreshListener; public MyLoadRefreshListener getLoadRefreshListener() { return mLoadRefreshListener; } public void setLoadRefreshListener(MyLoadRefreshListener loadRefreshListener) { mLoadRefreshListener = loadRefreshListener; } public interface MyLoadRefreshListener { // 获取现在item的类型 void getNowItemType(int itemPosition); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == RecyclerView.INVALID_TYPE) { //头部item return new RecyclerView.ViewHolder(headerViews.get(0)) { }; } else if (viewType == (RecyclerView.INVALID_TYPE - 1)) { //尾部item return new RecyclerView.ViewHolder(footViews.get(0)) { }; } return adapter.onCreateViewHolder(parent, viewType); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position >= 0 && position < headerViews.size()) { return; }// 交给 其他的适配器处理 if (adapter != null) { int p = position - headerViews.size(); if (p < adapter.getItemCount()) { adapter.onBindViewHolder(holder, p); } } } @Override public int getItemViewType(int position) { if (position >= 0 && position < headerViews.size()) { //如果是头部则返回一个不可用的标识,表示这是头部item return RecyclerView.INVALID_TYPE; } if (adapter != null) { int p = position - headerViews.size(); if (p < adapter.getItemCount()) { return adapter.getItemViewType(p); } } return RecyclerView.INVALID_TYPE - 1;//默认返回表示是尾部的item } @Override public int getItemCount() { return getCount(); } public int getCount() { int count = headerViews.size() + footViews.size(); if (adapter != null) { count += adapter.getItemCount(); } return count; }}
使用,添加监听
mHomeRecyclerview.setLayoutManager(new LinearLayoutManager(getContext())); MyHomeRecyclerviewAdapter adapter = new MyHomeRecyclerviewAdapter(LayoutInflater.from(getContext())); mHomeRecyclerview.setAdapter(adapter);// 设置 下拉刷新 和加载更多的 监听 mHomeRecyclerview.setMyRecyclerViewListener(new MyRecyclerView.MyRecyclerViewListener() { @Override public void onRefresh() { mHandler.postDelayed(new Runnable() { @Override public void run() { ToastUtils.showToast("onRefresh"); mHomeRecyclerview.setRefreshComplete(); } }, 2000); } @Override public void onLoadMore() { mHandler.postDelayed(new Runnable() { @Override public void run() { ToastUtils.showToast("onLoadMore"); mHomeRecyclerview.setLoadMoreComplete(); } }, 2000); } });
0 0
- 自定义的RecyclerView, 下拉刷新,加载更多.
- 自定义RecyclerView实现下拉刷新,加载更多
- YRecyclerView自定义下拉刷新上拉加载更多的RecyclerView
- 支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)
- SwipeRefreshLayout+RecyclerView 完成下拉刷新,上拉加载更多的自定义控件,简单好用
- 可以下拉刷新,上拉加载更多的RecyclerView
- RecyclerView的下拉刷新数据 与上拉加载更多
- RecyclerView的下拉刷新和加载更多 动画
- RecyclerView 上拉加载更多下拉刷新的一种实现
- RecyclerView 下拉刷新上拉加载更多
- RecyclerView下拉刷新和加载更多
- RecyclerView 下拉刷新上拉加载更多
- RecyclerView 下拉刷新、上拉加载更多
- RecyclerView 下拉刷新,自动加载更多
- RecyclerView 下拉刷新上拉加载更多
- recyclerview下拉刷新和加载更多
- RecyclerView上拉刷新,下拉加载更多
- RecyclerView 下拉刷新上拉加载更多
- eclipse启动tomcat无法访问
- react native封装原生view, 讲解其中的方案设计和通信机制,不错的分享
- Amdroid之系统桌面悬浮框(WindowManager)
- build一个没有签名的APP
- Linux系统配置sudo
- 自定义的RecyclerView, 下拉刷新,加载更多.
- Struts2学习整理总结
- leetCode练习(520)
- 基于bootstrap的中国地区(行政区)选择器
- 机器学习为什么需要训练,训练出来的模型具体又是什么?
- caffe︱Pascal VOC 2012 Multilabel Classification Model
- 什么是迭代
- 奇偶数分家
- Vulkan编程指南翻译 第五章 展现 第5节 开始呈现