使用RecyclerView绘制首页

前言
安卓5.0可以说是安卓变革的一代,谷歌在这一代开始引入了大量的材质设计(Material Design)使得view更加立体,感官上更让人舒服。同时也引入了很多新的控件,RecyclerView就是其中之一。

1.为啥要使用RecyclerView?
这篇文章详细的说明了RecyclerView适配器中的ViewHolder的复用性,比listview和gridview通过setTag和getTag从内存中获取之前实例化的view不知道高到哪去了。
https://www.2cto.com/kf/201607/522038.html
但是在照着网上的适配器写法写好之后你会发现,这就是个展示的view,每个item并没有对应的点击事件,你需要自己写对应的点击方法。当然这也方便我们自定义点击回调等方法。

2.绘制首页
那么废话不多说,先上图:
绘制的首页
如果不用RecyclerView,采取的方式一般是外层一个ScrollView,内部套ListView或者GridView(重写绘制方法)或者通过ListView加头的方式实现。那么RecyclerView该如何实现呢?

通常一个电商类的app拿到UI的设计图,整个app首页基本分为广告位,功能位(各个跳转按钮)和底部内容。
针对这3个部分,写3个对应的xml:
1)广告位

<?xml version="1.0" encoding="utf-8"?><!-- 头部广告 -->
<LinearLayout 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="wrap_content">

    <com.yoogonet.mainrecdemo.view.RecyclerViewBanner
        android:id="@+id/mainBanner"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        app:pointFocusBg="@color/red2_text"
        app:pointUnfocusBg="@color/really_white"
        app:point_size="30" />

</LinearLayout>

2)功能位

<?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"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮1"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮2"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮3"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮4"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

    </LinearLayout>

    <View style="@style/lineWidth" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin5"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮5"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin6"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮6"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin7"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮7"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

        <LinearLayout
            android:id="@+id/mainBodyLin8"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/bg_container_selector"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:src="@mipmap/ic_launcher_round" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="按钮8"
                android:textColor="@color/grey0_text"
                android:textSize="14sp" />
        </LinearLayout>

        <View style="@style/lineHeight" />

    </LinearLayout>

</LinearLayout>

3)底部内容

<?xml version="1.0" encoding="utf-8"?><!-- 底部列表 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/mainBottomImg"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:scaleType="centerCrop"
        android:src="@color/deep_black" />

</RelativeLayout>

首页适配器:

public class MainAdapter extends RecyclerView.Adapter<MainAdapter.BaseViewHolder> {
    private Context context;
    private GlideUtil mGlide;
    private OnADItemClickListener onADItemClickListener;//广告点击
    private OnLinItemClickListener onLinItemClickListener;//按钮点击
    private OnItemClickListener onItemClickListener;//底部点击
    private MainEntity mainEntity;//整体数据类
    private List<LinearLayout> mainLinDataList = new ArrayList<>();
    public static final int TYPE_HEADER = 1;//外部判断输出item的大小
    public static final int TYPE_BODY = 2;
    public static final int TYPE_BOTTOM = 3;

    public MainAdapter(MainEntity mainEntity) {
        this.mainEntity = mainEntity;
    }

    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        context = parent.getContext();
        if (null == mGlide) {
            mGlide = new GlideUtil(context);
        }
        View view = null;
        BaseViewHolder holder = null;
        switch (viewType) {
            case TYPE_HEADER:
                view = LayoutInflater.from(context).inflate(R.layout.item_main_header, null);
                holder = new MainHeaderViewHolder(view);
                break;
            case TYPE_BODY:
                view = LayoutInflater.from(context).inflate(R.layout.item_main_body, null);
                holder = new MainBodyViewHolder(view);
                break;
            case TYPE_BOTTOM:
                view = LayoutInflater.from(context).inflate(R.layout.item_main_bottom, null);
                holder = new MainBottomViewHolder(view);
                break;
        }
        return holder;
    }

    //返回所有可见的item的数量,如果传入的类包含集合这计算集合的长度让count++
    public int getItemCount() {
        return mainEntity.getShopDataList().size() + 2;
    }

    public int getItemViewType(int position) {
        if (0 == position) {
            return TYPE_HEADER;
        } else if (1 == position) {
            return TYPE_BODY;
        } else {
            return TYPE_BOTTOM;
        }
    }

    //给各个布局的赋值,position为item的数量,并不能指定每块内容里的item的下标
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        if (holder instanceof MainHeaderViewHolder) {
            List<String> bannerDataList = mainEntity.getBannerDataList();
            if (null != bannerDataList && !bannerDataList.isEmpty()) {
                ((MainHeaderViewHolder) holder).mainBanner.isShowIndicatorPoint(true);
                ((MainHeaderViewHolder) holder).mainBanner.setRvBannerDatas(bannerDataList);
                ((MainHeaderViewHolder) holder).mainBanner.setOnSwitchRvBannerListener((position1, bannerView) -> mGlide.displayNoPlaceholder(bannerView, bannerDataList.get(position1 % bannerDataList.size()), null));
                ((MainHeaderViewHolder) holder).mainBanner.setOnRvBannerClickListener(position2 -> {
                    if (null != onADItemClickListener) {
                        onADItemClickListener.setOnADItemClickListener(position2 % bannerDataList.size());
                    }
                });
            }
        } else if (holder instanceof MainBodyViewHolder) {
            if (null != mainLinDataList && !mainLinDataList.isEmpty()) {
                for (int i = 0; i < mainLinDataList.size(); i++) {
                    int linPosition = i;
                    mainLinDataList.get(i).setOnClickListener(v -> {
                        if (null != onLinItemClickListener) {
                            onLinItemClickListener.setOnLinItemClickListener(linPosition);
                        }
                    });
                }
            }
        } else if (holder instanceof MainBottomViewHolder) {
            List<ShopEntity> shopDataList = mainEntity.getShopDataList();
            if (null != shopDataList && shopDataList.size() > 1) {
                ShopEntity shopEntity = shopDataList.get(position - 2);
                if (null != shopEntity) {
                    mGlide.displayNoPlaceholder(((MainBottomViewHolder) holder).mainBottomImg, shopEntity.getUrl(), null);
                    ((MainBottomViewHolder) holder).mainBottomImg.setOnClickListener(v -> {
                        if (null != onItemClickListener) {
                            onItemClickListener.setOnItemClickListener(position - 2);
                        }
                    });
                }
            }
        }
    }

    //所有分级组键的基类
    class BaseViewHolder extends RecyclerView.ViewHolder {

        BaseViewHolder(View itemView) {
            super(itemView);
        }
    }

    //头部广告组键
    class MainHeaderViewHolder extends BaseViewHolder {
        private RecyclerViewBanner mainBanner;

        MainHeaderViewHolder(View view) {
            super(view);
            mainBanner = view.findViewById(R.id.mainBanner);
        }
    }

    //中部按钮组件(只做find布局操作,赋值部分交由onBindViewHolder去完成)
    class MainBodyViewHolder extends BaseViewHolder {
        private int mLinIds[] = {R.id.mainBodyLin, R.id.mainBodyLin2, R.id.mainBodyLin3, R.id.mainBodyLin4,
                R.id.mainBodyLin5, R.id.mainBodyLin6, R.id.mainBodyLin7, R.id.mainBodyLin8};//按钮id数据

        MainBodyViewHolder(View view) {
            super(view);
            for (int mLinId : mLinIds) {
                LinearLayout lin = view.findViewById(mLinId);
                mainLinDataList.add(lin);
            }
        }
    }

    //底部商品组件
    class MainBottomViewHolder extends BaseViewHolder {
        private ImageView mainBottomImg;

        MainBottomViewHolder(View view) {
            super(view);
            mainBottomImg = view.findViewById(R.id.mainBottomImg);
        }
    }

    //设置广告点击
    public void setOnADItemClickListener(OnADItemClickListener onADItemClickListener) {
        this.onADItemClickListener = onADItemClickListener;
    }

    //设置按钮点击
    public void setOnLinItemClickListener(OnLinItemClickListener onLinItemClickListener) {
        this.onLinItemClickListener = onLinItemClickListener;
    }

    //设置商品点击
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public interface OnADItemClickListener {
        void setOnADItemClickListener(int position);
    }

    public interface OnLinItemClickListener {
        void setOnLinItemClickListener(int position);
    }

    public interface OnItemClickListener {
        void setOnItemClickListener(int position);
    }

}

可以看到3部分的ViewHolder都继承了基础的BaseViewHolder,并且的getItemViewType中做了区分,需要注意的是,这个时候传入的集合要把其余加入的布局的数量加上,就比如我增加了头部的广告和中段的按钮,所以在总长度这里+2,并且在getItemViewType中,0和1返回的是头部和中段按钮。

接着就是写在主页写适配器的时候需要做一定的区分:
设置首页适配器,需要对占位做修改,比如底部数据的一行3个,配置manager的时候写了3,广告位1个就要占3个位置所以返回3,按钮位同理,那么底部按钮其实占的是1。

mainRecyclerView.setHasFixedSize(true);
GridLayoutManager manager = new GridLayoutManager(this, 3);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {

      public int getSpanSize(int position) {
          int viewType = mainAdapter.getItemViewType(position);
          int count = 1;
          switch (viewType) {
              case MainAdapter.TYPE_HEADER://首页头由于是一大块整体,占2个位置
                  count = 3;
                  break;
              case MainAdapter.TYPE_BODY:
                  count = 3;
                  break;
              case MainAdapter.TYPE_BOTTOM://底部 内容一个数据占一块
                  count = 1;
                  break;
          }
          return count;
      }
  });
  mainRecyclerView.setLayoutManager(manager);

//画间距
SparseArray<SCommonItemDecoration.ItemDecorationProps> propMap = new SparseArray<>();
SCommonItemDecoration.ItemDecorationProps prop1 = new SCommonItemDecoration.ItemDecorationProps(DisplayUtil.dip2px(this, 10), DisplayUtil.dip2px(this, 10), true, true);
propMap.put(MainAdapter.TYPE_BOTTOM, prop1);
mainRecyclerView.addItemDecoration(new SCommonItemDecoration(propMap));

配置好后即可完成绘制。

发布了4 篇原创文章 · 获赞 4 · 访问量 1406

猜你喜欢

转载自blog.csdn.net/heromrwang/article/details/82625759
今日推荐