赞
踩
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)
进行一个分类。
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);
- }
- }
- 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就可以了。
这样,大体上的效果我们就可以看到了:
基本上实现了需求,有一些细节的地方可能需求按自己的要求修改一下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。