RecyclerView加载多类型item 实现淘宝首页布局

主要为大家介绍如何用RecycleView来实现淘宝首页复杂的布局,做电商类app的小伙伴们可以略作参考。

首先上效果图:

下面说一下实现方式,主要思路就是根据不同的数据类型去制定不同的item类型,然后动态地去设置这些item的宽高,设置item的类型相信大家都会,我这里就不做阐述了,主要是说一下给不同类型的item设置不同的宽度。

首先,我们给RecyclerView设置一个列数为x的GridLayoutManager,然后再动态地为不同类型的item分别设置SpanSize。比如GridLayoutManager列数为4,item的SpanSize也为4,那么这个item的宽度就是RecyclerView宽度的100%,最终的效果就跟列表一样。同理,item的SpanSize如果是2,那么就占一行的一半宽度,item的SpanSize是1,占1/4宽度…

比如我在demo里面是把列数设为12:

HomeAdapter adapter = new HomeAdapter(this);
GridLayoutManager layoutManger = new GridLayoutManager(this, 12);
rcHome.setLayoutManager(layoutManger);
rcHome.setAdapter(adapter);
  • 1
  • 2
  • 3
  • 4

然后在adapter里面重写onAttachedToRecyclerView方法,为不同的ItemViewType设置不同的SpanSize:

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int type = getItemViewType(position);
                    switch (type) {
                        case BANNER:
                            return 12;
                        case COLUMN:
                            return 3;
                        case MARQUEE:
                            return 12;
                        case NUM_TWO:
                            return 6;
                        case TITLE:
                            return 12;
                        case NUM_THREE:
                            return 4;
                        case NORMAL:
                            return 6;
                        default:
                            return 12;
                    }
                }
            });
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

12代表宽度占满全屏,3代表占屏幕的1/4,6代表占屏幕的1/2等等,最终就可以实现上图中的效果。

代码不多,就直接贴在下面了:

MainActivity

public class MainActivity extends AppCompatActivity {
    private Unbinder mUnBinder;
    @BindView(R.id.rc_home)
    RecyclerView rcHome;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mUnBinder = ButterKnife.bind(this);
        initView();
    }

    private void initView() {
        HomeAdapter adapter = new HomeAdapter(this);
        GridLayoutManager layoutManger = new GridLayoutManager(this, 12);
        rcHome.setLayoutManager(layoutManger);
        rcHome.setAdapter(adapter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mUnBinder.unbind();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

HomeAdapter

public class HomeAdapter extends RecyclerView.Adapter {
    private LayoutInflater inflater;
    private List<Integer> imgList;
    private List<String> marqueeList;

    private static final int BANNER = 0;
    private static final int COLUMN = 1;
    private static final int MARQUEE = 2;
    private static final int NUM_TWO = 3;
    private static final int TITLE = 4;
    private static final int NUM_THREE = 5;
    private static final int NORMAL = 6;

    public HomeAdapter(Context mContext) {
        inflater = LayoutInflater.from(mContext);
        //添加轮播数据
        addBannerData();
        //添加跑马灯数据
        addMarqueeData();
    }

    @Override
    public int getItemCount() {
        return 25;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return BANNER;
        } else if (position >= 1 && position <= 8) {
            return COLUMN;
        } else if (position == 9) {
            return MARQUEE;
        } else if (position >= 10 && position <= 13) {
            return NUM_TWO;
        } else if (position == 14 || position == 18) {
            return TITLE;
        } else if (position >= 15 && position <= 17) {
            return NUM_THREE;
        } else if (position >= 19 && position <= 24) {
            return NORMAL;
        }
        return super.getItemViewType(position);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case BANNER:
                View itemBanner = inflater.inflate(R.layout.item_banner, parent, false);
                return new BannerHolder(itemBanner);
            case COLUMN:
                View itemColumn = inflater.inflate(R.layout.item_column, parent, false);
                return new ColumnHolder(itemColumn);
            case MARQUEE:
                View itemMarquee = inflater.inflate(R.layout.item_marquee, parent, false);
                return new MarqueeHolder(itemMarquee);
            case NUM_TWO:
                View itemNumTwo = inflater.inflate(R.layout.item_num_two, parent, false);
                return new NumTwoHolder(itemNumTwo);
            case TITLE:
                View itemTitle = inflater.inflate(R.layout.item_title, parent, false);
                return new TitleHolder(itemTitle);
            case NUM_THREE:
                View itemNumThree = inflater.inflate(R.layout.item_num_three, parent, false);
                return new NumThreeHolder(itemNumThree);
            case NORMAL:
                View itemNormal = inflater.inflate(R.layout.item_normal, parent, false);
                return new NormalHolder(itemNormal);
            default:
                return null;
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof BannerHolder) {
            setBanner((BannerHolder) holder);
        } else if (holder instanceof ColumnHolder) {

        } else if (holder instanceof MarqueeHolder && marqueeList != null) {
            setMarquee((MarqueeHolder) holder);
        } else if (holder instanceof NumTwoHolder) {

        } else if (holder instanceof TitleHolder) {
            setTitle((TitleHolder) holder, position);
        } else if (holder instanceof NumThreeHolder) {

        } else if (holder instanceof NormalHolder) {

        }
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int type = getItemViewType(position);
                    switch (type) {
                        case BANNER:
                            return 12;
                        case COLUMN:
                            return 3;
                        case MARQUEE:
                            return 12;
                        case NUM_TWO:
                            return 6;
                        case TITLE:
                            return 12;
                        case NUM_THREE:
                            return 4;
                        case NORMAL:
                            return 6;
                        default:
                            return 12;
                    }
                }
            });
        }
    }

    public class BannerHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.banner)
        Banner banner;

        BannerHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    public class ColumnHolder extends RecyclerView.ViewHolder {

        public ColumnHolder(View itemView) {
            super(itemView);
        }
    }

    public class MarqueeHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.marquee)
        UPMarqueeView marquee;

        public MarqueeHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    public class NumTwoHolder extends RecyclerView.ViewHolder {

        public NumTwoHolder(View itemView) {
            super(itemView);
        }
    }

    public class TitleHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.tv_title)
        TextView tvTitle;

        public TitleHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    public class NumThreeHolder extends RecyclerView.ViewHolder {

        public NumThreeHolder(View itemView) {
            super(itemView);
        }
    }


    public class NormalHolder extends RecyclerView.ViewHolder {

        public NormalHolder(View itemView) {
            super(itemView);
        }
    }

    /**
     * 轮播图图片列表
     */
    private void addBannerData() {
        imgList = new ArrayList<>();
        imgList.add(R.drawable.home_pic);
        imgList.add(R.drawable.home_pic);
        imgList.add(R.drawable.home_pic);
    }

    /**
     * 添加跑马灯数据
     */
    private void addMarqueeData() {
        marqueeList = new ArrayList<>();
        marqueeList.add("太疯狂!IPhone X首批1分钟卖光。");
        marqueeList.add("家人给2岁孩子喝这个,孩子智力倒退10岁!");
        marqueeList.add("自助餐里面的潜规则,想要吃回本其实很简单。");
        marqueeList.add("简直是白菜价!日本玩家33万甩卖15万张游戏王卡。");
    }

    /**
     * 绑定轮播图数据
     */
    private void setBanner(BannerHolder holder) {
        holder.banner.setBannerStyle(BannerConfig.NUM_INDICATOR);
        holder.banner.setImageLoader(new GlideImageLoader());
        holder.banner.setImages(imgList);
        holder.banner.setBannerAnimation(Transformer.Default);
        holder.banner.isAutoPlay(true);
        holder.banner.setDelayTime(3000);
        holder.banner.setIndicatorGravity(BannerConfig.CENTER);
        holder.banner.start();
    }

    /**
     * 设置跑马灯
     */
    private void setMarquee(MarqueeHolder holder) {
        List<View> views = new ArrayList<>();
        for (int i = 0; i < marqueeList.size(); i = i + 2) {
            LinearLayout view = (LinearLayout) inflater.inflate(R.layout.marquee_text, null);
            TextView textTop = (TextView) view.findViewById(R.id.text_top);
            TextView textBottom = (TextView) view.findViewById(R.id.text_bottom);
            textTop.setText(marqueeList.get(i));
            if (marqueeList.size() > i + 1) {
                textBottom.setText(marqueeList.get(i + 1));
            }
            views.add(view);
        }
        holder.marquee.setViews(views);
    }

    /**
     * 模块标题
     */
    private void setTitle(TitleHolder holder, int position) {
        switch (position) {
            case 14:
                holder.tvTitle.setText("精品推荐");
                break;
            case 18:
                holder.tvTitle.setText("猜你喜欢");
                break;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253

最后附上完整的Demo下载:
http://download.csdn.net/download/a466302603/10048064

--------------------- 本文来自 卡蓝_ 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/a466302603/article/details/78411612?utm_source=copy

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值