RecyclerView多item实现3

2019-10-25  本文已影响0人  jiluyixia

首页的最后一个布局,如图:


Screenshot_2019-10-25-17-36-31-016_com.li.gohome.png

这个布局,可以分三个部分。
第一部分,就是那个title,左边一个图片,右边一个text,下面带个分割线。
第二部分,2个大图片。
第三部分,4个小图片。
由于是均分布局,很容易想到,又是用的RecyclerView+GridLayoutManager。

在主RecyclerView中,这3部分还是作为一个RecyclerView整体,方便设置圆弧背景。
设置单独的bean文件:

public class SalesBoxBean extends ExampleBaseBean {
    private SalesBox salesbox;

    public SalesBox getSalesboxBean() {
        return salesbox;
    }

    public void setSalesboxBean(SalesBox salesbox) {
        this.salesbox = salesbox;
    }
}

添加数据:

SalesBoxBean salesBoxBean = new SalesBoxBean();
salesBoxBean.setSalesboxBean(model.getSalesbox());
salesBoxBean.setViewType(SALES_TYPE);
datas.add(salesBoxBean);

然后是添加Holder:

public class SalesHolder extends RecyclerView.ViewHolder {
        RecyclerView salesRecycler;

        public SalesHolder(@NonNull View itemView) {
            super(itemView);
            salesRecycler = itemView.findViewById(R.id.sales_recycler);
        }
    }

else if (viewType == SALES_TYPE) {
            return new SalesHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.sales_box, parent, false));
}

根据typeview实现SalesHolder:

else if (holder instanceof SalesHolder) {
            SalesBoxBean salesBoxBean = (SalesBoxBean) datas.get(position);
            RecyclerView recyclerView = ((SalesHolder) holder).salesRecycler;
            recyclerView.setLayoutManager(new GridLayoutManager(context, 2, RecyclerView.VERTICAL, false));
            recyclerView.setAdapter(new SalesAdapter(salesBoxBean.getSalesboxBean()));
}

这个SalesHolder布局就是一个RecyclerView。
根据前面的分析,用RecyclerView+GridLayoutManager实现这部分布局。
spancount设置为2(和后面的onAttachedToRecyclerView配合使用,设置占据空间大小。),salesBoxBean.getSalesboxBean()数据传递给SalesAdapter。
这个布局稍微有点复杂,先看看这个数据SalesBox的组成。

public class SalesBox {
    private String icon;
    private String moreUrl;
    private CommonModel bigCard1;
    private CommonModel bigCard2;
    private CommonModel smallCard1;
    private CommonModel smallCard2;
    private CommonModel smallCard3;
    private CommonModel smallCard4;
    .....
}

icon是title左边的图片,moreUrl是点击右边文字进入的链接。
下面是2个大图和4个小图。
根据前面的分析,这个RecyclerView分为3大布局,7个item(title作为一个占满widht的整体,加上6个1/2widht屏幕的图片)。
title:sales_title.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="44dp"
    >

    <com.li.gohome.util.MyImageView
        android:id="@+id/sales_title_left"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_width="wrap_content"
        android:scaleType="fitXY"
        android:layout_height="15dp"/>

    <TextView
        android:id="@+id/sales_title_right"
        android:layout_marginRight="3dp"
        android:text="获得更多福利>"
        android:textSize="12dp"
        android:paddingLeft="10dp"
        android:paddingRight="8dp"
        android:paddingTop="1dp"
        android:paddingBottom="1dp"
        android:textColor="@android:color/white"
        android:background="@drawable/sales_text_bg"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="1dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:background="#f2f2f2"/>

</androidx.constraintlayout.widget.ConstraintLayout>

这个title布局,有几个要注意的地方:
首先是image,发现设置了hight,这个图片的高度并没有变化,于是找到了一个属性
android:scaleType="fitXY",对应flutter代码里面也设置了fit: BoxFit.fill,这个属性能让图片撑满布局。
然后就是textview,
他有一个渐变的背景,这里设置了一个渐变的xml:
android:background="@drawable/sales_text_bg"

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <!-- 指定圆角矩形的4个圆角的半径 -->
    <corners android:topLeftRadius="12dp"
        android:topRightRadius="12dp"
        android:bottomLeftRadius="12dp"
        android:bottomRightRadius="12dp"
        />

    <!-- 指定使用渐变背景色,使用sweep类型的渐变,颜色从红色到绿色再到蓝色 -->
    <gradient android:startColor="#ffff4e63"
        android:endColor="#ffff6cc9"
        android:angle="45"
        android:centerX="0.5"
        android:centerY="0.5"

        />
</shape>

corners设置圆角,gradient设置渐变色。
[android:angle]渐变色的角度,举例来说,0代表从上至下颜色渐变;45代表从左至右颜色渐变;90代表从下至上颜色渐变…
文字和背景有一定的距离,这里就要用

android:paddingLeft="10dp"
android:paddingRight="8dp"
android:paddingTop="1dp"
android:paddingBottom="1dp"

来设置一下文字和背景的距离。
android:layout_marginRight="3dp"是整个textview距离外面的布局。

Padding 为内边框,指该控件内部内容,如文本/图片距离该控件的边距
Margin 为外边框,指该控件距离边父控件的边距。

接下来,是两种图片。
sales_big_image.xml:

<?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">

    <com.li.gohome.util.MyImageView
        android:id="@+id/sales_big_image"
        android:layout_width="match_parent"
        android:layout_height="129dp"/>

</LinearLayout>

sales_small_image.xml
和上面一样,只是高度为80dp。

注意,sales_title.xml和下面的2个图片,widht都要为match_parent,要不然不能撑满空间。

回到SalesAdapter。
Holder布局:

public class TitleHolder extends RecyclerView.ViewHolder {
        MyImageView imageView;
        TextView textView;

        public TitleHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.sales_title_left);
            textView = itemView.findViewById(R.id.sales_title_right);
        }
    }

    public class ImageBigHolder extends RecyclerView.ViewHolder {
        MyImageView imageView;

        public ImageBigHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.sales_big_image);
        }
    }

    public class ImageSmallHolder extends RecyclerView.ViewHolder {
        MyImageView imageView;

        public ImageSmallHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.sales_small_image);
        }
 }

关键点在getItemViewType。

 public int getItemViewType(int position) {
        if (position == 0) {
            return TITLE_TYPE;
        } else if (position == 1 || position == 2) {
            return IMAGE_BIG_TYPE;
        }else if(position > 2){
            return IMAGE_SMALL_TYPE;
        }
        return super.getItemViewType(position);
}

position为0的时候,为TITLE_TYPE,1和2的时候是IMAGE_BIG_TYPE,剩下4个是IMAGE_SMALL_TYPE。
用onAttachedToRecyclerView来确定他们7个item占的布局空间:

public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    if (TITLE_TYPE == getItemViewType(position)) {
                        return 2;
                    } else if (IMAGE_BIG_TYPE == getItemViewType(position)
                    || IMAGE_SMALL_TYPE == getItemViewType(position)) {
                        return 1;
                    } else {
                        return 2;
                    }
                }
            });
        }
}

onAttachedToRecyclerView方法和前面设置的spancount一起配合,2为占满屏,1为一半屏。
onCreateViewHolder绑定Holder:

if (viewType == TITLE_TYPE) {
            return new TitleHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.sales_title, parent, false));
        } else if (viewType == IMAGE_BIG_TYPE) {
            return new ImageBigHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.sales_big_image, parent, false));
        }else if (viewType == IMAGE_SMALL_TYPE) {
            return new ImageSmallHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.sales_small_image, parent, false));
}

将数据加入到集合方便调用:

private List<String> datas = new ArrayList<>();
datas.add(salesbox.getIcon());
datas.add(salesbox.getMoreUrl());
datas.add(salesbox.getBigCard1().getIcon());
datas.add(salesbox.getBigCard2().getIcon());
datas.add(salesbox.getSmallCard1().getIcon());
datas.add(salesbox.getSmallCard2().getIcon());
datas.add(salesbox.getSmallCard3().getIcon());
datas.add(salesbox.getSmallCard4().getIcon());

salesbox.getIcon和salesbox.getMoreUrl作为title整体,所以

public int getItemCount() {
        return datas.size() - 1;
}

接下来,onBindViewHolder绑定数据:

if (holder instanceof TitleHolder) {
            ((TitleHolder) holder).imageView.setImageURL(salesbox.getIcon());
        } else if (holder instanceof ImageBigHolder) {
            ((ImageBigHolder) holder).imageView.setImageURL(datas.get(position+1));
        } else if (holder instanceof ImageSmallHolder) {
            ((ImageSmallHolder) holder).imageView.setImageURL(datas.get(position+1));
}

这样,整个布局就完成了,详见代码:
https://github.com/doudousang/recyclerview_items2.git

参考代码:
Android中设置Imageview的图片充满整个布局
android 圆角边框、渐变背景的TextView
Android RecyclerView加载复杂布局
Android在ImageView上直接显示网络图片

上一篇 下一篇

猜你喜欢

热点阅读