RecyclerView 多布局使用
来源:互联网 发布:阿里云 短信 编辑:程序博客网 时间:2024/05/18 18:18
RecyclerView 使用了很久了,一直是简单的和ListView 一样的效果。其实RecyclerView 的强大之处在于实现一线复杂的布局,这是ListView 不能做到的。对于基本的RecyclerView 使用我们都很熟悉了,今天写一个多布局的实现。先看需求图:
需求如上:对于“历史选择”这个条目以上的部分我们可以写一个LinearLayout 就处理了。“历史选择”一下的部分我们用RecyclerView 去实现。(以前的思路我们可能是ScrollView 加listView 嵌套来实现这个需求)
我们看上图画了一些框,“历史选择”为一行,位置的信息如:嘉峪关则一行有四个格子,下面的灰色分割线也是占满了一行,还有“选择省份”也是一行,下面的省份的名称如“甘肃”,也是一行。大概我们就可以看明白了有五种不同的布局要处理,历史选择,地点名称的小格子,灰色分割线,选择省份一行,省份名称一行,他们占的padding是不同的,我们只能用多个布局来处理。这样我们就可以开始写布局了。
历史选择:就一个TextView
<TextView android:id="@+id/tv_selectHistoryTitle" tools:text="历史选择:" android:textColor="@color/black" android:padding="@dimen/padding_10dp" android:paddingLeft="@dimen/padding_15dp" android:layout_width="match_parent" android:layout_height="wrap_content" />显示地名的小格子布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:gravity="center" android:id="@+id/ll_content" android:background="@color/white" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/margin_4dp" android:layout_marginRight="@dimen/margin_4dp" android:layout_marginTop="@dimen/margin_5dp" android:layout_marginBottom="@dimen/margin_5dp"> <TextView android:id="@+id/tv_selectPlaceContent" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:background="@drawable/bg_bit_gray_hollow_rounded_rectangle" android:ellipsize="end" android:lines="1" android:paddingLeft="@dimen/padding_6dp" android:paddingRight="@dimen/padding_6dp" android:paddingTop="@dimen/padding_6dp" android:paddingBottom="@dimen/padding_6dp" android:textColor="@color/black" tools:text="历史选择的的" /></LinearLayout>其中给TextView 添加一个drawable ,也就是一个shape就可以成为途中的椭圆的样子了。
下面是选择省份这个标题,也是一个TextView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/lightgray" android:orientation="vertical"> <TextView android:id="@+id/tv_selectProvinceTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:paddingLeft="@dimen/padding_10dp" android:paddingRight="@dimen/padding_10dp" android:paddingTop="@dimen/padding_10dp" android:textColor="@color/black" tools:text="选择省粉:" /></LinearLayout>最后是显示省份名称的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:paddingBottom="@dimen/padding_5dp" android:paddingTop="@dimen/padding_5dp" xmlns:tools="http://schemas.android.com/tools"> <TextView android:id="@+id/tv_selectProvinceName" tools:text="甘肃" android:textColor="@color/black" android:layout_marginLeft="@dimen/margin_10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>这样就完成了上面分析的布局的编写。
然后写RecyclerView 和Adapter适配器。对于多布局的实现,主要是要对数据进行分类,我们根据不同的类别在Adapter中返回不同的ViewHoler就可以了。和其他的Adapter相比,我们需要多写一个方法
public int getItemViewType(int position)进行一个分类。
其实前面我们可以看出来这个对于RecyclerView 来说我们要使用一个GridLayoutManager 布局管理器,让他显示为四列的样子,对于那些标题部分显示的是一列,我们可以重写一个方法,让在这个类型的布局的时候显示一列就有可以了。所以说这个多布局中主要还有一个方法:
gridLayoutManager.setSpanSizeLookup()这个就是用来设置显示几列的方法。
下面看代码:
private Context context; private List<PlaceItem> list; private final int SPAN_SIZE_HISTORY_CHOICE = 1001;//,历史选择 private final int SPAN_SIZE_CHOICE_PROVINCE = 1002;//标题,选择省 private final int SPAN_SIZE_PROVINCE_NAME = 1003;//选择的省名称 private final int SPAN_SIZE_CONTENT = 1004;//位置数据 private final int SPAN_SIZE_GRAY_SEPARATE = 1005;//灰色分割条 private OnPlaceItemClickListener onPlaceItemClickListener; public void setOnPlaceItemClickListener(OnPlaceItemClickListener onPlaceItemClickListener) { this.onPlaceItemClickListener = onPlaceItemClickListener; } public SelectPlaceAdapter(Context context, List<PlaceItem> list) { this.context = context; this.list = list; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(viewType == SPAN_SIZE_GRAY_SEPARATE){ View separateView = LayoutInflater.from(context).inflate(R.layout.recycle_select_place_item_gray_bg, parent, false); SelectPlaceGraybgViewHolder viewHolder = new SelectPlaceGraybgViewHolder(separateView); return viewHolder; }else if (viewType == SPAN_SIZE_HISTORY_CHOICE) { View historyView = LayoutInflater.from(context).inflate(R.layout.recycle_select_place_item_history_select_title, parent, false); SelectHistoryTitleViewHolder viewHolder = new SelectHistoryTitleViewHolder(historyView); return viewHolder; } else if (viewType == SPAN_SIZE_CHOICE_PROVINCE) { View provinceTitleView = LayoutInflater.from(context).inflate(R.layout.recycle_select_place_item_select_province_title, parent, false); SelectProvinceTitleViewHolder viewHolder = new SelectProvinceTitleViewHolder(provinceTitleView); return viewHolder; } else if (viewType == SPAN_SIZE_PROVINCE_NAME) { View provinceNameView = LayoutInflater.from(context).inflate(R.layout.recycle_select_place_item_subtitle, parent, false); SelectProvinceNameViewHolder viewHolder = new SelectProvinceNameViewHolder(provinceNameView); return viewHolder; } else if (viewType == SPAN_SIZE_CONTENT) { View contentView = LayoutInflater.from(context).inflate(R.layout.recycle_select_place_item_content, parent, false); SelectPlaceContentViewHoder viewHolder = new SelectPlaceContentViewHoder(contentView); return viewHolder; } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int type = getItemViewType(position); Log.e("TAG", "bindViewHolder type-" + type); switch (type) { case SPAN_SIZE_GRAY_SEPARATE:{ SelectPlaceGraybgViewHolder selectPlaceGraybgViewHolder = (SelectPlaceGraybgViewHolder) holder; GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) selectPlaceGraybgViewHolder.llSelectPlaceGraybg.getLayoutParams(); DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); layoutParams.width = displayMetrics.widthPixels; layoutParams.setMarginStart(DensityUtil.dp2px(context,-10));//设置左边移动,从(0,0)开始 selectPlaceGraybgViewHolder.llSelectPlaceGraybg.setLayoutParams(layoutParams); selectPlaceGraybgViewHolder.llSelectPlaceGraybg.requestLayout(); break; } case SPAN_SIZE_HISTORY_CHOICE: { SelectHistoryTitleViewHolder historyTitleViewHolder = (SelectHistoryTitleViewHolder) holder; historyTitleViewHolder.tvSelectHistoryTitle.setText("历史选择title"); break; } case SPAN_SIZE_CHOICE_PROVINCE: { SelectProvinceTitleViewHolder provinceTitleViewHolder = (SelectProvinceTitleViewHolder) holder; provinceTitleViewHolder.tvSlectProvinceTitdle.setText("选择省份:"); break; } case SPAN_SIZE_PROVINCE_NAME: { SelectProvinceNameViewHolder provinceNameViewHolder = (SelectProvinceNameViewHolder) holder; provinceNameViewHolder.tvSelectProvinceName.setText("甘肃省"); break; } case SPAN_SIZE_CONTENT: { SelectPlaceContentViewHoder contentViewHoder = (SelectPlaceContentViewHoder) holder; contentViewHoder.itemView.setOnClickListener(v -> { if(onPlaceItemClickListener!=null){ onPlaceItemClickListener.onItemClick(contentViewHoder.itemView,position); } }); contentViewHoder.tvSelectPlaceContent.setText(list.get(position).getItemContent()); break; } } } @Override public int getItemCount() { return list.size(); } @Override public int getItemViewType(int position) { if (list.get(position).getItemType() == 1) { return SPAN_SIZE_HISTORY_CHOICE;//1001 } else if (list.get(position).getItemType() == 2) { return SPAN_SIZE_CHOICE_PROVINCE;//1002 } else if (list.get(position).getItemType() == 3) { return SPAN_SIZE_PROVINCE_NAME;//1003 } else if (list.get(position).getItemType() == 4) { return SPAN_SIZE_CONTENT;//1004 } else if(list.get(position).getItemType() == 5){ return SPAN_SIZE_GRAY_SEPARATE; }else{ return SPAN_SIZE_CONTENT;//默认是内容返回 } } /** * 位置点击 */ public interface OnPlaceItemClickListener{ void onItemClick(View view,int postion); } /** * 历史选择 标题 */ public class SelectHistoryTitleViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.tv_selectHistoryTitle) TextView tvSelectHistoryTitle; public SelectHistoryTitleViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } /** * 选择省粉 标题 */ public class SelectProvinceTitleViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.tv_selectProvinceTitle) TextView tvSlectProvinceTitdle; public SelectProvinceTitleViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } /** * 省份名称显示 */ public class SelectProvinceNameViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.tv_selectProvinceName) TextView tvSelectProvinceName; public SelectProvinceNameViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } /** * 地点显示 */ public class SelectPlaceContentViewHoder extends RecyclerView.ViewHolder { @BindView(R.id.tv_selectPlaceContent) TextView tvSelectPlaceContent; @BindView(R.id.ll_content) LinearLayout llContent; public SelectPlaceContentViewHoder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } /** * 灰色条 */ public class SelectPlaceGraybgViewHolder extends RecyclerView.ViewHolder{ @BindView(R.id.ll_selectPlaceGraybg) LinearLayout llSelectPlaceGraybg; public SelectPlaceGraybgViewHolder(View itemView) { super(itemView); ButterKnife.bind(this,itemView); } }
每一个布局我们都写一个ViewHolder 总共有5个ViewHolder。上面我们重写了getItemViewType ()这个方法,主要是根据数据的类型返回不同的类型。然后在onCreateViewHolder 中根据类型判断穿件不同的ViewHolder.最后在onBindViewHolder()中绑定数据就可以了。接着来看看显示一行时候调用的方法:
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int type = recycleSelectPlace.getAdapter().getItemViewType(position); switch (type){ case 1004:{ return 1;//占1格 } case 1001:{ return 4; } case 1002:{ return 4; } case 1003:{ return 4; } case 1005:{ return 4; } } return 4; } });代码很简单,就是根据type,return 要占的格子数就好了。其中的type值和Adapter中的类型对应。
数据部分:我们要按照图中从上到下(历史选择->历史选择的数据->选择省份:标题->省份名称->省份数据->省份名称...)的顺序处理好,在数据对象中添加一个type,然后添加到List 中传递进Adapter就可以了。
这样,大体上的效果我们就可以看到了:
基本上实现了需求,有一些细节的地方可能需求按自己的要求修改一下。
- RecyclerView 多布局使用
- Android RecyclerView 详解(五) RecyclerView多布局的使用
- RecyclerView的使用(三)多布局
- RecyclerView实现多布局
- RecyclerView的多布局
- 实现RecyclerView多布局
- RecyclerView多布局实现
- Android recyclerView 多布局
- RecyclerView 多布局问题
- RecyclerView多布局实现
- RecyclerView多布局加载
- recyclerview 多布局
- RecyclerView多布局
- recyclerView多布局
- RecyclerView多布局适配器
- recyclerView多条目布局
- 解析 RecyclerView多布局
- RecyclerView使用(头尾布局)
- NC开发笔记——单据模板编辑显示公式使用
- C#中Socket通信编程的异步实现
- iOS 判断网络连接状态的几种方法
- Foursquare数据集处理之利用defaultdict进行主次关键字排序
- leetcode- Beautiful Arrangement II
- RecyclerView 多布局使用
- httpURLConnection
- 5-1 使用函数计算分段函数的值
- Android中的ContentProvider小结
- Unity Mono.Data.Sqlite.dll System.Data.dll路径问题
- CRC16
- 解决清除浮动的问题
- kettle学习导航帖整理
- 递归算法:全排列、2的幂次方表示