RecyclerView的demo
来源:互联网 发布:深圳冰川网络 编辑:程序博客网 时间:2024/05/18 00:27
作为listview的升级版,这个技能是绝对值得点上的
recyclerview需要导包:compile 'com.android.support:recyclerview-v7:26.0.+'
布局: <android.support.v7.widget.RecyclerView //可以设置rv的方向 android:orientation="Vertical" android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="300dp"> </android.support.v7.widget.RecyclerView>
创建adapter继承于RecyclerView.adapter<holder>public class MyAdapter extends RecyclerView.Adapter<MyAdapter.Holder> { List<String> datas; public MyAdapter(List<String> datas) { this.datas = datas; } @Override public int getItemCount() { return datas.size(); } //返回holder类 @Override public Holder onCreateViewHolder(ViewGroup parent, int viewType) { return new Holder(View.inflate(parent.getContext(),R.layout.tab_item,null)); } //绑定数据 @Override public void onBindViewHolder(Holder holder, int position) { //通过该方法来展示不同类型的item int type = getItemViewType(position); switch (type){ case 1: holder.iv.setImageResource(R.mipmap.ic_launcher); break; case 2: holder.iv.setImageResource(R.mipmap.ic_launcher_round); break; } holder.tv.setText(datas.get(position)); //顺便一提,rv并没有lv中setitemclick()的监听方法,需要监听item事件可以在这里通过 //view.onclick(内部类)的方式设置事件监听 } //通过该方法可以设置在rv中展示不同类型的item @Override public int getItemViewType(int position) { if ((position%2)==1){ return 1; }else{ return 2; } } //创建holder类继承于RecyclerView.ViewHolder,并通过传入的view来初始化子控件 public class Holder extends RecyclerView.ViewHolder { ImageView iv; TextView tv; public Holder(View itemView) { super(itemView); setView(itemView); } public void setView(View view){ iv = view.findViewById(R.id.tab_imageview); tv = view.findViewById(R.id.tab_textview); } }}
展示: //创建随机长度的数据 private void initData() { datas=new ArrayList<>(); for (int i = 0; i < 100; i++) { int times = new Random().nextInt(30); StringBuilder sb =new StringBuilder(); for (int j = 0; j < times; j++) { sb.append("哈哈"); } datas.add(sb.toString()+i); } } private void show() { MyAdapter ada = new MyAdapter(datas); rv.setAdapter(ada); //线性布局 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); //可以设置方向 linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); rv.setLayoutManager(linearLayoutManager); rv.setLayoutManager(new GridLayoutManager(this,3)); //瀑布流布局 rv.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL)); }
设置recyclerview的分割线
方法一:在item布局中设置margin<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="50dp" android:orientation="vertical"> <ImageView android:id="@+id/tab_imageview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:background="#0000ff" /> <TextView android:id="@+id/tab_textview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="10dp" //在recyclerview中设置不同的颜色 android:background="#0000ff" android:textColor="@drawable/selector" /></LinearLayout>
调用mRecyclerView.addItemDecoration();不过,需要手动实现分割线 //实现分割线 public class DivLineDemo extends RecyclerView.ItemDecoration{ //会在子类被绘制之前调用,所以会在item图层下面 @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); } //在子类被绘制之后绘制,所以绘制的图形会覆盖item @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); } //像padding和margin,可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator。 @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { //每个item距离下方的item有3dp的分割线,实现了类似margin的效果 outRect.set(0,0,0,3); } }
网络找来的一份线性布局的分割线demo/** * 调用了系统的分割线,可以在样式中自定义分隔线的样式 */-------------------------------------------------------------------------------------public class DivLine 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 Drawable mDivider; private int mOrientation; private DivLine(){} public DivLine(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } public void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public 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; i++) { final View child = parent.getChildAt(i); android.support.v7.widget.RecyclerView v = new android.support.v7.widget.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); } } public 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; 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); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } }}-----------------------------------------------------------------------------------在style中自定义分割线的样式<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> //自定义分割线样式 <item name="android:listDivider">@drawable/divider_bg</item> </style></resources>创建一个shape位图<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:centerColor="#ff00ff00" android:endColor="#ff0000ff" android:startColor="#ffff0000" android:type="linear"/> <size android:height="4dp"/></shape>
转自网络,gridlayoutmanger的分割线----------------------------------------------------------------------------------------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, State state) { drawHorizontal(c, parent); drawVertical(c, parent); } private int getSpanCount(RecyclerView parent) { // 列数 int spanCount = -1; 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) { 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) { 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()); } }}----------------------------------------------------------------------------------------
Recycler添加头布局和脚布局
public class HeaderFooterAdapter extends RecyclerView.Adapter<HeaderFooterAdapter.Holder> { //头布局和脚布局,并添加相应的get set方法 View header; View footer; public void setHeader(View view) { header = view; } public void setFooter(View view) { footer = view; } public View getHeader() { return header; } public View getFooter() { return footer; } //普通数据 List<String> datas; public HeaderFooterAdapter(List<String> datas) { this.datas = datas; } //通过判断头布局和脚布局是否为空,返回的count不同 @Override public int getItemCount() { int num = datas.size(); if (header != null) num++; if (footer != null) num++; return num++; } //返回holder类,头布局和脚布局直接返回 @Override public Holder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 8) return new Holder(footer); if (viewType == 9) { return new Holder(header); } return new Holder(View.inflate(parent.getContext(), R.layout.tab_item, null)); } //绑定数据 @Override public void onBindViewHolder(Holder holder, int position) { //通过该方法来展示不同类型的item int type = getItemViewType(position); switch (type) { case 1: holder.iv.setImageResource(R.mipmap.ic_launcher); if (header != null) holder.tv.setText(datas.get(position - 1)); else holder.tv.setText(datas.get(position)); break; case 2: holder.iv.setImageResource(R.mipmap.ic_launcher_round); if (header != null) holder.tv.setText(datas.get(position - 1)); else holder.tv.setText(datas.get(position)); break; case 8: break; case 9: break; } } //通过该方法可以设置在rv中展示不同类型的item @Override public int getItemViewType(int position) { if (header != null) { if (position == 0) { //9的意思是头布局 return 9; } } if (footer != null) { //footer不为空,且是最后一位 if (position == getItemCount() - 1) { //8的意思是脚布局 return 8; } } if ((position % 2) == 1) { return 1; } else { return 2; } } //创建holder类继承于RecyclerView.ViewHolder,并通过传入的view来初始化子控件 public class Holder extends RecyclerView.ViewHolder { ImageView iv; TextView tv; public Holder(View itemView) { super(itemView); //如果是头布局和脚布局,则直接返回 if (itemView == header) return; if (itemView == footer) return; setView(itemView); } public void setView(View view) { iv = view.findViewById(R.id.tab_imageview); tv = view.findViewById(R.id.tab_textview); } }}
自定义布局管理器
对于各种奇葩需求,有时候我们只能自己上了,还好rv中可以自定义layoutmangerpublic class MyLayoutManager extends RecyclerView.LayoutManager { final MyLayoutManager self = this; //默认的布局的宽高参数 @Override public RecyclerView.LayoutParams generateDefaultLayoutParams() { return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); } //布局的入口,这里我们做一个斜着对齐的linearlayoutmanager @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { super.onLayoutChildren(recycler, state); //该方法的作用是分离所有的item的视图,将原本rv中item全部解绑 detachAndScrapAttachedViews(recycler); int offsetX = 0; int offsetY = 0; //获取item个数的方法getItemCount() for (int i = 0; i < getItemCount(); i++) { // 根据position获取一个碎片view,可以从回收的view中获取,也可能新构造一个 View scrap = recycler.getViewForPosition(i); //遍历获取总高度,在处理滚动事件的时候有用 totalHeight+=scrap.getHeight(); //因为已经detach所以可以重新添加 addView(scrap); // 计算此碎片view包含边距的尺寸 measureChildWithMargins(scrap, 0, 0); int width = getDecoratedMeasuredWidth(scrap); // 获取此碎片view包含边距和装饰的宽度width int height = getDecoratedMeasuredHeight(scrap); // 获取此碎片view包含边距和装饰的高度height // 布局到RecyclerView容器中,所有的计算都是为了得出任意position的item的边界来布局 layoutDecorated(scrap, offsetX , offsetY, offsetX + width, offsetY + height); offsetX += width; offsetY += height; if (offsetX+width>=getWidth()) offsetX=0; } } //处理垂直方向上的滑动 @Override public boolean canScrollVertically() { return true; } //总偏移量 int verticalScrollOffset; //所有item的总高度 int totalHeight; @Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { //列表向下滚动dy为正,列表向上滚动dy为负,这点与Android坐标系保持一致。 //实际滑动的距离 int travel = dy; //如果滑动到最顶部,则设置为0 if (verticalScrollOffset + dy < 0) { travel = 0; } //如果滑动到了最底部 else if (verticalScrollOffset + dy > totalHeight - getHeight()) { travel = totalHeight - getHeight() - verticalScrollOffset; } //将竖直方向的偏移量+travel verticalScrollOffset += travel; // 调用该方法通知view在y方向上移动指定距离,滑动和方向与item滚动的方向相反 offsetChildrenVertical(-travel); return travel; }}
recyclerview加载多重item布局
//可惜不能用泛型,需要自己强转public class ParentRecordAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { List<JsonParentRecord> mDatas = new ArrayList<>(); public void addDatas(List<JsonParentRecord> datas) { mDatas.addAll(0,datas); }//通过判断type返回不同的viewholder @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 0) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.directormailbox_get_item, parent, false); ViewHolder0 viewHolder = new ViewHolder0(view); return viewHolder; } else { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.directormailbox_send_item, parent, false); ViewHolder1 viewHolder = new ViewHolder1(view); return viewHolder; } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //判断类型,并进行强转 if (holder instanceof ViewHolder0) { //todo } else if (holder instanceof ViewHolder1) { //todo } } @Override public int getItemCount() { return mDatas.size(); } public List<JsonParentRecord> getDatas() { return mDatas; }//在这里返回不同类型的type @Override public int getItemViewType(int position) { //0为学生,在左边 return mDatas.get(position).getType(); }//创建多个viewholder类 class ViewHolder0 extends RecyclerView.ViewHolder { //type0 TextView tv_content_stu; TextView tv_time_stu; public ViewHolder0(View layout) { super(layout); tv_content_stu = layout.findViewById(R.id.textview_directormailbox_get_coonten); tv_time_stu = layout.findViewById(R.id.textview_directormailbox_get_time); } } class ViewHolder1 extends RecyclerView.ViewHolder { //type1 TextView tv_content_parents; TextView tv_time_parents; public ViewHolder1(View layout) { super(layout); tv_content_parents = layout.findViewById(R.id.textview_directormailbox_send_coonten); tv_time_parents = layout.findViewById(R.id.textview_directormailbox_send_time); layout.findViewById(R.id.textview_directormailbox_send_nimingshifou).setVisibility(View.GONE); layout.findViewById(R.id.textview_directormailbox_send_biaoshi).setVisibility(View.GONE); } }}
阅读全文
0 0
- recyclerview的demo
- RecyclerView的demo
- Recyclerview 常见问题的 Demo 解决办法
- 简单的Android RecyclerView 使用小Demo
- 一个RecyclerView写出来的小Demo
- RecyclerView分组列表的实现及demo
- Kotlin和RecyclerView的一个demo
- Android RecyclerView使用Demo
- RecyclerView学习demo
- RecyclerView+CardView+共享元素+调色板的综合demo
- [Android开发]从Android官方Demo谈RecyclerView的用法
- android 包含了JNI,,fresco,RecyclerView的DEMO
- RecyclerView实现listview+GridView之间切换的小demo
- RecyclerView 使用 和简单demo
- RecyclerView 多条目加载demo
- RecyclerView上拉加载Demo
- 一个精简的实现RecyclerView可添加header和footer的Demo
- Android 结合RecyclerView,CardView,和swipeRefreshLayout下拉刷新做的简单demo
- iOS开发:开发过程中单例模式的使用
- 彻底征服 Spring AOP 之 理论篇
- centos系统性能监控常用软件介绍
- 带你玩遍c语言(1)关键字
- Java事物
- RecyclerView的demo
- 编译RT288X SDK安装mksquash_lzma-3.2报错
- 计算机编码模式
- scroll实现上拉加载,下拉刷新,轮播图效果
- Eclipse如何给web项目打war包
- Material Design之底部导航栏
- c++远航之const
- ArcEngnine中IHookHelper的用法
- 线程(1)---创建线程的两种方式