RecyclerView常用功能解析
来源:互联网 发布:网络攻击的发展趋势是 编辑:程序博客网 时间:2024/06/16 19:34
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
1. RecyclerView常用功能
- 普通的上下滑动和左右滑动
- Grid效果上下滑动和左右滑动
- 瀑布流的上下滑动和左右滑动
- 添加分割线
- 去除最后一个item的分割线
- 添加点击事件
- 增加和删除item
- 添加动画
- 多布局
- 下拉刷新和上拉加载
- 添加头布局和脚布局
- 拖拽排序和侧滑删除
- 分页加载、上拉加载、添加脚布局DEMO
2. RecyclerView相关类
- RecyclerView.Adapter :创建子项item布局和绑定数据
- RecyclerView.ViewHolder :生成子项item的布局
- RecyclerView.LayoutManager :设置子项item的排列方式
- RecyclerView.ItemDecoration : 设置子项item的分割线
- RecyclerView.ItemAnimator : 设置子项item的动画
3. RecyclerView基本实现
- 依赖:
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
- 布局:
<?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="match_parent" > <android.support.v7.widget.RecyclerView android:id="@+id/main_recyclerview" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView></LinearLayout>
- 设置布局管理器和Adapter
public class MainActivity extends AppCompatActivity { private RecyclerView mMain_recyclerview; private List<String> mList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initData(); initAdapter(); } //初始化控件 private void initView() { setContentView(R.layout.activity_main); mMain_recyclerview = (RecyclerView) findViewById(R.id.main_recyclerview); } //初始化数据 private void initData() { mList = new ArrayList<>(); for (int i = 0; i < 10; i++) { mList.add("纵向和横向滑动"); mList.add("纵向和横向瀑布流"); mList.add("添加头布局和脚布局"); mList.add("下拉刷新和上拉加载"); mList.add("多布局页面"); mList.add("滑动删除"); mList.add("点击事件"); mList.add("添加空布局"); mList.add("添加分割线"); } } //初始化Adapter private void initAdapter() { //设置布局管理器 mMain_recyclerview.setLayoutManager(new LinearLayoutManager(this)); //初始化和设置Adapter MainAdapter mainAdapter = new MainAdapter(mList); mMain_recyclerview.setAdapter(mainAdapter); }}
- Adapter:
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> { private List<String> mList; public MainAdapter(List<String> list) { mList = list; } //创建子项item的布局 @Override public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_item, parent, false); return new ViewHolder(view); } //给控件设置数据 @Override public void onBindViewHolder(MainAdapter.ViewHolder holder, int position) { holder.tv_main.setText(mList.get(position)); } //子项item的数量 @Override public int getItemCount() { return mList.size(); } //初始化子项控件 static class ViewHolder extends RecyclerView.ViewHolder { TextView tv_main; public ViewHolder(View itemView) { super(itemView); this.tv_main = itemView.findViewById(R.id.tv_main); } }}
4. RecyclerView左右和上下滑动以及瀑布流:
- 只需修改布局管理器参数即可:
//ListView形式上下滑动:mMain_recyclerview.setLayoutManager(new LinearLayoutManager(this));//左右滑动:LinearLayoutManager magager = new LinearLayoutManager(this);magager.setOrientation(LinearLayoutManager.HORIZONTAL);//Grid形式上下滑动:GridLayoutManager layoutManager = new GridLayoutManager(this,4);//Grid形式左右滑动:GridLayoutManager layoutManager = new GridLayoutManager(this, 4);layoutManager.setOrientation(GridLayoutManager.HORIZONTAL);//瀑布流形式上下滑动:StaggeredGridLayoutManager layoutManager = newStaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);//瀑布流形式左右滑动:StaggeredGridLayoutManager layoutManager = newStaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL);
5. ListView形式上下滑动和左右滑动添加分割线:
- 添加分割线:
mMain_recyclerview.addItemDecoration(new MyDividerItemDecoration(this, MyDividerItemDecoration.VERTICAL_LIST));
- MyDividerItemDecoration
ondraw:绘制 getItemOffsets:绘制的区域
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private int mOrientation; private Drawable mDivider; private int mDividerHeight = 2; //默认是2px private Paint mPaint; //绘制默认分割线 public MyDividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); //系统属性中获取 a.recycle(); setOrientation(orientation); } /** * 自定义分割线 * * @param context * @param orientation 列表方向 * @param drawableId 分割线图片 */ public MyDividerItemDecoration(Context context, int orientation, int drawableId) { this(context, orientation); mDivider = ContextCompat.getDrawable(context, drawableId); mDividerHeight = mDivider.getIntrinsicHeight(); } /** * 自定义分割线 * * @param context * @param orientation 列表方向 * @param dividerHeight 分割线高度 * @param dividerColor 分割线颜色 */ public MyDividerItemDecoration(Context context, int orientation, int dividerHeight, int dividerColor) { this(context, orientation); mDividerHeight = dividerHeight; mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(dividerColor); mPaint.setStyle(Paint.Style.FILL); } private void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientaion"); } mOrientation = orientation; } @Override //在RecyclerView的onDraw中执行 public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } private void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount-1; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount-1; i++) { final View child = parent.getChildAt(i); RecyclerView v = new RecyclerView(parent.getContext()); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDividerHeight); } else { outRect.set(0, 0, mDividerHeight, 0); } }}
6. Grid和瀑布流形式添加分割线
- 添加分割线:
mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
- DividerGridItemDecoration(Grid和瀑布流形式都可用):
public class DividerGridItemDecoration extends RecyclerView.ItemDecoration{ private static final int[] ATTRS = new int[] { android.R.attr.listDivider }; private Drawable mDivider; public DividerGridItemDecoration(Context context) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { drawHorizontal(c, parent); drawVertical(c, parent); } private int getSpanCount(RecyclerView parent) { // 列数 int spanCount = -1; RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); } else if (layoutManager instanceof StaggeredGridLayoutManager) { spanCount = ((StaggeredGridLayoutManager) layoutManager) .getSpanCount(); } return spanCount; } public void drawHorizontal(Canvas c, RecyclerView parent) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int left = child.getLeft() - params.leftMargin; final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawVertical(Canvas c, RecyclerView parent) { final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int top = child.getTop() - params.topMargin; final int bottom = child.getBottom() + params.bottomMargin; final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) { RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 { return true; } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL) { if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 { return true; } } else { childCount = childCount - childCount % spanCount; if (pos >= childCount)// 如果是最后一列,则不需要绘制右边 return true; } } return false; } private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) { RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { childCount = childCount - childCount % spanCount; if (pos >= childCount)// 如果是最后一行,则不需要绘制底部 return true; } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); // StaggeredGridLayoutManager 且纵向滚动 if (orientation == StaggeredGridLayoutManager.VERTICAL) { childCount = childCount - childCount % spanCount; // 如果是最后一行,则不需要绘制底部 if (pos >= childCount) return true; } else // StaggeredGridLayoutManager 且横向滚动 { // 如果是最后一行,则不需要绘制底部 if ((pos + 1) % spanCount == 0) { return true; } } } return false; } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { int spanCount = getSpanCount(parent); int childCount = parent.getAdapter().getItemCount(); if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部 { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边 { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight()); } }}
6. RecyclerView去除最后一个item的分割线
ListView形式:在上面的分割线绘制部分,我们只绘制了childCount-1个,所以上面的分割线,已经不会绘制最后一条item的分割线了。
Grid和瀑布流形式:首先去判断是不是最后一行或者一列,然后在getItemOffsets方法中不绘制底部或者右边,上面的部分已经实现。
7. RecyclerView添加点击事件
- 处理点击事件,只需要在Adapter中处理即可:
public class PortraitAdapter extends RecyclerView.Adapter<PortraitAdapter.ViewHolder> { private List<Fruit> mFruitList; private boolean flag = true; public PortraitAdapter(List<Fruit> fruitList) { mFruitList = fruitList; } static class ViewHolder extends RecyclerView.ViewHolder { ImageView fruitImage; TextView fruitName; LinearLayout ll_portraitscape; public ViewHolder(View view) { super(view); fruitImage = (ImageView) view.findViewById(R.id.fruit_image); fruitName = (TextView) view.findViewById(R.id.fruit_name); ll_portraitscape = (LinearLayout) view.findViewById(R.id.ll_portraitscape); } } @Override public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_portrait, parent, false); final ViewHolder holder = new ViewHolder(view); holder.ll_portraitscape.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { new AlertDialog.Builder(v.getContext()) .setTitle("确认删除吗") .setNegativeButton("取消",null) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (flag == true){ removeData(holder.getAdapterPosition()); flag=false; }else{ addData(holder.getAdapterPosition()); flag=true; } } }) .show(); return false; } }); holder.fruitImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(parent.getContext(),"我是图片短点击",Toast.LENGTH_SHORT).show(); } }); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); } @Override public int getItemCount() { return mFruitList.size(); } public void addData(int position) { mFruitList.add(position, new Fruit("Apple", R.drawable.apple_pic)); notifyItemInserted(position); } public void removeData(int position) { mFruitList.remove(position); notifyItemRemoved(position); }}只需要在onCreateViewHolder中处理即可,可以很轻松实现子项中任意控件或布局的点击事件。
7. RecyclerView增加和删除item
- 在Adapter添加两种方法
public void addData(int position) { mFruitList.add(position, new Fruit("Apple", R.drawable.apple_pic)); notifyItemInserted(position); } public void removeData(int position) { mFruitList.remove(position); notifyItemRemoved(position); }
- 在Adapter中的onCreateViewHolder中的点击事件里面添加动作
holder.ll_portraitscape.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { new AlertDialog.Builder(v.getContext()) .setTitle("确认删除吗") .setNegativeButton("取消",null) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (flag == true){ removeData(holder.getAdapterPosition()); flag=false; }else{ addData(holder.getAdapterPosition()); flag=true; } } }) .show(); return false; } });
8. RecyclerView添加动画效果
- 默认的动画:
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
- 自定义的动画:
private int mLastPosition;//放在成员变量的位置上if (viewHolder.getAdapterPosition() > mLastPosition) { ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewHolder.itemView, "scaleX", 0.5f, 1f); scaleX.start(); mLastPosition = viewHolder.getLayoutPosition();}
说明:实现的方式有很多种,这里介绍一种,就是在RecyclerView的onBindViewHolder中利用属性动画就可以实现非常华丽的效果。
9. RecyclerView多布局
- 实现多布局最核心的方法就是在Adapter中重写getItemViewType方法:
@Overridepublic int getItemViewType(int position) { if (mNewsBeanList.get(position).getThumbnail_pic_s03() == null) { return IMAGE_ONLY_ONE; } else { return IMAGE_TWOORTHREE; }}
说明:判断下布局的不同,返回不同的值,不同的值就代表了不多的布局。
- 在onCreateViewHolder方法中第二个参数对应的就是上面方法返回的值,我们根据值的不同,填充不同的布局。
@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { if (viewType == IMAGE_TWOORTHREE) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.news_imagethree_item, viewGroup, false); ImageThreeViewHolder viewHolder = new ImageThreeViewHolder(view); return viewHolder; } else { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.news_imageonly_item, viewGroup, false); ImageOnlyOneViewHolder viewHolder = new ImageOnlyOneViewHolder(view); return viewHolder; }}
- 不同的布局需要不同的ViewHolder
static class ImageThreeViewHolder extends RecyclerView.ViewHolder { private TextView mTv_title; private ImageView mIv_image01; private ImageView mIv_image02; private ImageView mIv_image03; private TextView mTv_company; private TextView mTv_time; private View mItemView; public ImageThreeViewHolder(View itemView) { super(itemView); mItemView = itemView; mTv_title = itemView.findViewById(R.id.tv_title); mIv_image01 = itemView.findViewById(R.id.iv_image01); mIv_image02 = itemView.findViewById(R.id.iv_image02); mIv_image03 = itemView.findViewById(R.id.iv_image03); mTv_company = itemView.findViewById(R.id.tv_company); mTv_time = itemView.findViewById(R.id.tv_time); } } static class ImageOnlyOneViewHolder extends RecyclerView.ViewHolder { private View mItemView; private TextView mTv_title; private TextView mTv_company; private TextView mTv_time; private ImageView mIv_image01; public ImageOnlyOneViewHolder(View itemView) { super(itemView); mItemView = itemView; mTv_title = itemView.findViewById(R.id.tv_title); mTv_company = itemView.findViewById(R.id.tv_company); mTv_time = itemView.findViewById(R.id.tv_time); mIv_image01 = itemView.findViewById(R.id.iv_image01); } }
- onBindViewHolder方法中的第一个参数对应不同的viewholder,我们通过判断,来进行每个元素的写入
@Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { if (viewHolder instanceof ImageThreeViewHolder) { ((ImageThreeViewHolder) viewHolder).mTv_title.setText(mNewsBeanList.get(position).getTitle()); ((ImageThreeViewHolder) viewHolder).mTv_company.setText(mNewsBeanList.get(position).getAuthor_name()); ((ImageThreeViewHolder) viewHolder).mTv_time.setText(mNewsBeanList.get(position).getDate()); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s()).into(((ImageThreeViewHolder) viewHolder).mIv_image01); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s02()).into(((ImageThreeViewHolder) viewHolder).mIv_image02); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s03()).into(((ImageThreeViewHolder) viewHolder).mIv_image03); } else if (viewHolder instanceof ImageOnlyOneViewHolder) { ((ImageOnlyOneViewHolder) viewHolder).mTv_title.setText(mNewsBeanList.get(position).getTitle()); ((ImageOnlyOneViewHolder) viewHolder).mTv_company.setText(mNewsBeanList.get(position).getAuthor_name()); ((ImageOnlyOneViewHolder) viewHolder).mTv_time.setText(mNewsBeanList.get(position).getDate()); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s()).into(((ImageOnlyOneViewHolder) viewHolder).mIv_image01); } }
10. RecyclerView 上拉刷新和下拉加载
- 下拉刷新(借助SwipeRefreshLayout)
private void initRefresh() { srRefresh.setColorSchemeResources(R.color.colorPrimary); srRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refreshFruits(); } }); } private void refreshFruits() { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { initFruits(); adapter.notifyDataSetChanged(); srRefresh.setRefreshing(false); } }); } }).start(); } private void initFruits() { fruitList.clear(); for (int i = 0; i < 50; i++) { Random random = new Random(); int index = random.nextInt(fruits.length); fruitList.add(fruits[index]); } }
说明:SwipeRefreshLayout设置一个监听器:setOnRefreshListener,onRefresh方法中进行数据更新的操作。
- 上拉加载
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (adapter.isFadeTips() == false && lastVisibleItem + 1 == adapter.getItemCount()) { mHandler.postDelayed(new Runnable() { @Override public void run() { updateRecyclerView(adapter.getRealLastPosition(), adapter.getRealLastPosition() + PAGE_COUNT); } }, 500); } if (adapter.isFadeTips() == true && lastVisibleItem + 2 == adapter.getItemCount()) { mHandler.postDelayed(new Runnable() { @Override public void run() { updateRecyclerView(adapter.getRealLastPosition(), adapter.getRealLastPosition() + PAGE_COUNT); } }, 500); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); lastVisibleItem = mLayoutManager.findLastVisibleItemPosition(); } });
说明:recyclerView添加滑动监听器addOnScrollListener,在onScrollStateChanged方法中处理加载的动作。
11. RecyclerView添加头布局和脚布局
添加头布局和脚布局,其实和实现多布局一模一样,不再赘述。
12. RecyclerView拖曳排序和侧滑删除
private void initBind() { //为RecycleView绑定触摸事件 ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() { @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //侧滑删除 int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //首先回调的方法 返回int表示是否监听该方向 int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;//拖拽 return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { //滑动事件 Collections.swap(list, viewHolder.getAdapterPosition(), target.getAdapterPosition()); adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { //侧滑事件 list.remove(viewHolder.getAdapterPosition()); adapter.notifyItemRemoved(viewHolder.getAdapterPosition()); } @Override public boolean isLongPressDragEnabled() { //是否可拖拽 return true; } }); helper.attachToRecyclerView(recyclerView); }
11. 分页加载、上拉加载、添加脚布局DEMO
分页加载的核心代码:
private final int PAGE_COUNT = 10;
adapter = new MyAdapter(getDatas(0, PAGE_COUNT), this, getDatas(0, PAGE_COUNT).size() > 0 ? true : false);
private List<String> getDatas(final int firstIndex, final int lastIndex) { List<String> resList = new ArrayList<>(); for (int i = firstIndex; i < lastIndex; i++) { if (i < list.size()) { resList.add(list.get(i)); } } return resList; } private void updateRecyclerView(int fromIndex, int toIndex) { List<String> newDatas = getDatas(fromIndex, toIndex); if (newDatas.size() > 0) { adapter.updateList(newDatas, true); } else { adapter.updateList(null, false); } }
Adapter:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<String> datas; private Context context; private int normalType = 0; private int footType = 1; private boolean hasMore = true; private boolean fadeTips = false; private Handler mHandler = new Handler(Looper.getMainLooper()); private static final String TAG = "MyAdapter"; public MyAdapter(List<String> datas, Context context, boolean hasMore) { this.datas = datas; this.context = context; this.hasMore = hasMore; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == normalType) { return new NormalHolder(LayoutInflater.from(context).inflate(R.layout.item, null)); } else { return new FootHolder(LayoutInflater.from(context).inflate(R.layout.footview, null)); } } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { if (holder instanceof NormalHolder) { ((NormalHolder) holder).textView.setText(datas.get(position)); } else { ((FootHolder) holder).tips.setVisibility(View.VISIBLE); if (hasMore == true) { fadeTips = false; if (datas.size() > 0) { ((FootHolder) holder).tips.setText("正在加载更多..."); } } else { if (datas.size() > 0) { ((FootHolder) holder).tips.setText("没有更多数据了"); mHandler.postDelayed(new Runnable() { @Override public void run() { ((FootHolder) holder).tips.setVisibility(View.GONE); fadeTips = true; hasMore = true; } }, 500); } } } } @Override public int getItemCount() { return datas.size() + 1; } public int getRealLastPosition() { return datas.size(); } public void updateList(List<String> newDatas, boolean hasMore) { if (newDatas != null) { datas.addAll(newDatas); } this.hasMore = hasMore; notifyDataSetChanged(); } class NormalHolder extends RecyclerView.ViewHolder { private TextView textView; public NormalHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.tv); } } class FootHolder extends RecyclerView.ViewHolder { private TextView tips; public FootHolder(View itemView) { super(itemView); tips = (TextView) itemView.findViewById(R.id.tips); } } public boolean isFadeTips() { return fadeTips; } public void resetDatas() { datas = new ArrayList<>(); } @Override public int getItemViewType(int position) { Log.e(TAG,"getItemCount()::"+getItemCount()); Log.e(TAG,"position::"+position); if (position == getItemCount() - 1) { return footType; } else { return normalType; } }}
Activity
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener { private SwipeRefreshLayout refreshLayout; private RecyclerView recyclerView; private List<String> list; private int lastVisibleItem = 0; private final int PAGE_COUNT = 10; private LinearLayoutManager mLayoutManager; private MyAdapter adapter; private Handler mHandler = new Handler(Looper.getMainLooper()); private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); findView(); initRefreshLayout(); initRecyclerView(); } private void initData() { list = new ArrayList<>(); for (int i = 1; i <= 40; i++) { list.add("条目" + i); } } private void findView() { refreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshLayout); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); } private void initRefreshLayout() { refreshLayout.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_red_light, android.R.color.holo_orange_light, android.R.color.holo_green_light); refreshLayout.setOnRefreshListener(this); } private void initRecyclerView() { adapter = new MyAdapter(getDatas(0, PAGE_COUNT), this, getDatas(0, PAGE_COUNT).size() > 0 ? true : false); mLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(mLayoutManager); recyclerView.setAdapter(adapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (adapter.isFadeTips() == false && lastVisibleItem + 1 == adapter.getItemCount()) { mHandler.postDelayed(new Runnable() { @Override public void run() { updateRecyclerView(adapter.getRealLastPosition(), adapter.getRealLastPosition() + PAGE_COUNT); } }, 500); } if (adapter.isFadeTips() == true && lastVisibleItem + 2 == adapter.getItemCount()) { mHandler.postDelayed(new Runnable() { @Override public void run() { Log.e(TAG, "lastVisibleItem::" + lastVisibleItem); Log.e(TAG, "adapter.getItemCount()::" + adapter.getItemCount()); updateRecyclerView(adapter.getRealLastPosition(), adapter.getRealLastPosition() + PAGE_COUNT); } }, 500); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); lastVisibleItem = mLayoutManager.findLastVisibleItemPosition(); Log.e(TAG, "lastVisibleItem::" + lastVisibleItem); Log.e(TAG, "adapter.getItemCount()::" + adapter.getItemCount()); } }); } private List<String> getDatas(final int firstIndex, final int lastIndex) { List<String> resList = new ArrayList<>(); for (int i = firstIndex; i < lastIndex; i++) { if (i < list.size()) { resList.add(list.get(i)); } } return resList; } private void updateRecyclerView(int fromIndex, int toIndex) { List<String> newDatas = getDatas(fromIndex, toIndex); if (newDatas.size() > 0) { adapter.updateList(newDatas, true); } else { adapter.updateList(null, false); } } @Override public void onRefresh() { refreshLayout.setRefreshing(true); adapter.resetDatas(); updateRecyclerView(0, PAGE_COUNT); mHandler.postDelayed(new Runnable() { @Override public void run() { refreshLayout.setRefreshing(false); } }, 1000); }}
详细说明:http://blog.csdn.net/ljcITworld/article/details/70160820
下载地址:https://github.com/OnlyYouMyLove/PullToLoadData-RecyclerView
阅读全文
1 0
- RecyclerView常用功能解析
- RecyclerView 解析
- RecyclerView 解析
- RecyclerView 解析
- RecyclerView解析
- RecyclerView解析
- RecyclerView解析
- Java 常用功能三--解析XML
- RecyclerView的长按多选功能
- recyclerview的适配器功能
- RecyclerView实现ListView功能
- RecyclerView功能集封装
- RecyclerView Prefetch功能探究
- RecyclerView加载不同item并实现其item点击事件,实现添加常用应用的功能
- EasyRecyclerView,简单易上手,支持多种常用的功能的RecyclerView
- RecyclerView CardView使用解析
- Android RecyclerView 使用解析
- RecyclerView完全解析
- Caffe从入门到精通03
- 第八周项目三 对称矩阵压缩存储的实现与应用(1)
- LeetCode.290 Word pattern
- Linux下,VMware Tools 安装失败
- 图片水平垂直居中方案
- RecyclerView常用功能解析
- C++实现循环队列
- Leetcode——第88题
- codecademy SQL 编程系列三Create && Insert , Select
- Java作业杨枝10.28/10.29
- 对Servlet的理解
- Day01_Java作业
- 杭电 1015 Safecracker
- NOIP模拟(10.30)T1 比赛