首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Android】RecyclerView多布局展示案例

【Android】RecyclerView多布局展示案例

作者头像
三三是该溜子
发布2025-08-21 08:31:16
发布2025-08-21 08:31:16
2110
举报
文章被收录于专栏:该溜子的专栏该溜子的专栏

三三要成为安卓糕手

零:需求

怎么在recycle中实现不同的item样式,如新闻列表中不同样式 item(单图、双图、三图、广告)的展示。

下面先对代码逻辑进行设计分析

其执行逻辑顺序可以分为初始化阶段数据准备阶段RecyclerView 渲染阶段三个核心部分

一、初始化阶段

  1. **onCreate**方法触发 当 Activity 启动时,调用onCreate方法
    • 加载布局:activity_article_more_list),布局中包含RecyclerView控件
    • 初始化RecyclerView:通过findViewById获取RecyclerView实例,并为其设置布局管理器(垂直线性布局)

二、数据准备阶段(数据源创建与传递)

  1. 创建数据源 调用createData()方法生成模拟数据,具体逻辑:
    • 最终返回包含 22 条数据的列表(20 条新闻 + 2 条广告,广告通过add(索引, 对象)插入到指定位置)。
  2. 初始化适配器并传递数据
    • 创建ArticleMoreAdapter实例(适配器是RecyclerView与数据之间的桥梁)。
    • 通过adapter.setArticles(articles)将数据源传递给适配器,适配器内部会调用notifyDataSetChanged()通知RecyclerView:“数据已更新,请重新渲染”。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三、RecyclerView 渲染阶段(核心流程)

RecyclerView通过适配器(ArticleMoreAdapter)完成从数据到 UI 的渲染,核心步骤由getItemCountgetItemViewTypeonCreateViewHolderonBindViewHolder四个方法协作完成,执行顺序如下:

1. getItemCount():确定列表长度

适配器首先调用此方法,返回articles.size()(即 22),告诉RecyclerView:“需要展示 22 条数据”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. getItemViewType(int position):确定每条数据的布局类型

重写adpter中的getItemViewType方法,根据不同的position决定里面到底显示成什么样

对每个位置(0 到 21),RecyclerView会调用此方法判断该位置应使用哪种布局:

  • article.isIdAd()true(广告),返回ITEM_TYPE_AD
  • 若只有 1 张图片(picture2picture3为 0),返回ITEM_TYPE_ARTICLE_1
  • 若有 2 张图片(picture3为 0),返回ITEM_TYPE_ARTICLE_2
  • 若有 3 张图片,返回ITEM_TYPE_ARTICLE_3。 (作用:为不同数据匹配不同布局,实现多样式展示)

节点:已经完成了告诉recycleview返回一个不同的viewtype,这个viewtype是根据我们数据本身来做决定的;

现在要做的是:告诉recycelvie 怎么样根据不同的viewtype做出一些view的关联

3. onCreateViewHolder(ViewGroup parent, int viewType):创建布局对应的 ViewHolder

根据getItemViewType返回值,传参给viewType,创建对应布局的ViewHolder(布局与控件的管理者):

  • viewTypeITEM_TYPE_ARTICLE_1:加载item_article_simple.xml布局,创建MyViewHolder(管理单张图片、标题、作者)。
  • 若为ITEM_TYPE_ARTICLE_2:加载item_article_picture2.xml,创建MyViewHolder2(管理两张图片、标题、作者)。
  • 若为ITEM_TYPE_ARTICLE_3:加载item_article_picture3.xml,创建MyViewHolder3(管理三张图片、标题、作者)。
  • 若为ITEM_TYPE_AD:加载item_article_ad.xml,创建AdViewHolder(管理广告图片和关闭按钮)。 (作用:将 XML 布局转换为 Java 可操作的 View,并通过 ViewHolder 缓存控件,提升性能)

4. onBindViewHolder(ViewHolder holder, int position)

绑定数据到控件对每个位置,将数据中的内容设置到ViewHolder缓存的控件中:

  • 根据position获取对应Article对象和viewType
  • 若为ITEM_TYPE_ARTICLE_2:通过MyViewHolder2ivPicture1ivPicture2设置两张图片,tvTitle设置标题,tvAuthor设置作者。
  • 若为ITEM_TYPE_AD:通过AdViewHolderivPicture设置广告图片。
  • 其他类型同理,完成数据与 UI 的绑定。 (作用:将数据源中的数据 “填充” 到布局控件中,最终展示到屏幕上)

我只能说非常这一集炸裂,搞了好久,终于从宏观角度把代码逻辑梳理清楚了

代码语言:javascript
复制
package com.xlong.myapplication.recyclerview;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.xlong.myapplication.R;

import java.util.ArrayList;

public class ArticleMoreAdapter extends RecyclerView.Adapter {
    public static final int ITEM_TYPE_ARTICLE_1 = 1;//对应一张图片的itemView
    public static final int ITEM_TYPE_ARTICLE_2 = 2;//对应2张图片itemView
    public static final int ITEM_TYPE_ARTICLE_3 = 3;//对应3张图片的itemView
    public static final int ITEM_TYPE_AD = 4;//对应广告的itemView


    private static final String TAG = "ArticleMoreAdapter";
    private ArrayList<Article> articles;

    //构造函数中不装东西就可以完成初始化工作了
    public ArticleMoreAdapter() {
    }

    public void setArticles(ArrayList<Article> articles) {
        this.articles = articles;
        //告诉adapter,关联的数据源有变化,请重新根据数据做出调整
        notifyDataSetChanged();
        Log.i(TAG, "setArticles: article.size = " + articles.size());
    }



    public ArrayList<Article> getArticles() {
        return articles;
    }

    /**
     * 数据如何与item布局做关联
     * 其实就是根据拿到的不同的viewType创建对应的ViewHolder(不同类型的杯子)
     */
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //找item布局,把item转为视图,与LayoutInflater有异曲同工之处
        Log.i(TAG, "onCreateViewHolder: viewType = " + viewType);
        switch (viewType) {
            case ITEM_TYPE_ARTICLE_2:
                View view2 = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.item_article_picture2, parent, false);
                return new MyViewHolder2(view2);

            case ITEM_TYPE_ARTICLE_3:
                View view3 = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.item_article_picture3, parent, false);
                return new MyViewHolder3(view3);


            case ITEM_TYPE_AD:
                View viewAd = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.item_article_ad, parent, false);
                return new AdViewHolder(viewAd);

            case ITEM_TYPE_ARTICLE_1:
            default:
                //查找item布局
                View view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.item_article_simple, parent, false);

                //创建一个ViewHolder对itemView做管理
                MyViewHolder myViewHolder = new MyViewHolder(view);
                //ViewHolder和RecyclerView做关联
                return myViewHolder;
        }

    }

    /**
     * 有一条item就调用一次这个方法
     */
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        Log.i(TAG, "onBindViewHolder: position" + position);

        //通过position获取对应的viewType
        int itemViewType = getItemViewType(position);
        Article article = articles.get(position);

        switch (itemViewType) {
            case ITEM_TYPE_ARTICLE_2:
                MyViewHolder2 holder2 = (MyViewHolder2) holder;
                holder2.ivPicture1.setImageResource(article.getPicture());
                holder2.ivPicture2.setImageResource(article.getPicture2());
                holder2.tvTitle.setText(article.getTitle());
                holder2.tvAuthor.setText(article.getAuthor());
                break;
            case ITEM_TYPE_ARTICLE_3:
                MyViewHolder3 holder3 = (MyViewHolder3) holder;
                holder3.ivPicture1.setImageResource(article.getPicture());
                holder3.ivPicture2.setImageResource(article.getPicture2());
                holder3.ivPicture3.setImageResource(article.getPicture3());
                holder3.tvTitle.setText(article.getTitle());
                holder3.tvAuthor.setText(article.getAuthor());
                break;
            case ITEM_TYPE_AD:
                AdViewHolder holderAd = (AdViewHolder) holder;
                holderAd.ivPicture.setImageResource(article.getAdPicture());
                break;
            case ITEM_TYPE_ARTICLE_1:
            default:
                MyViewHolder holderSimple = (MyViewHolder) holder;
                holderSimple.ivPicture.setImageResource(article.getPicture());
                holderSimple.tvTitle.setText(article.getTitle());
                holderSimple.tvAuthor.setText(article.getAuthor());
                break;
        }
    }


    @Override
    public int getItemViewType(int position) {
        Article article = articles.get(position);
        if (article.isIdAd()) {
            return ITEM_TYPE_AD;
        } else if (article.getPicture2() == 0 && article.getPicture3() == 0) {
            return ITEM_TYPE_ARTICLE_1;
        } else if (article.getPicture3() == 0) {
            return ITEM_TYPE_ARTICLE_2;
        } else {
            return ITEM_TYPE_ARTICLE_3;
        }
    }

    /**
     * @return 告诉RecyclerView显示多少条数据
     */
    @Override
    public int getItemCount() {
        Log.i(TAG, "getItemCount: articles的数量为" + articles);
        return articles == null ? 0 : articles.size();
    }




    public class MyViewHolder extends RecyclerView.ViewHolder {

        private final ImageView ivPicture;
        private final TextView tvTitle;
        private final TextView tvAuthor;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            ivPicture = itemView.findViewById(R.id.iv_picture);
            tvTitle = itemView.findViewById(R.id.tv_title);
            tvAuthor = itemView.findViewById(R.id.tv_author);
        }
    }

    /**
     * 两张图片的ViewHolder
     */
    public class MyViewHolder2 extends RecyclerView.ViewHolder {

        private final ImageView ivPicture1;
        private final ImageView ivPicture2;

        private final TextView tvTitle;
        private final TextView tvAuthor;

        public MyViewHolder2(@NonNull View itemView) {
            super(itemView);

            ivPicture1 = itemView.findViewById(R.id.iv_picture1);
            ivPicture2 = itemView.findViewById(R.id.iv_picture2);
            tvTitle = itemView.findViewById(R.id.tv_title);
            tvAuthor = itemView.findViewById(R.id.tv_author);
        }
    }

    public class MyViewHolder3 extends RecyclerView.ViewHolder {
        private final ImageView ivPicture1;
        private final ImageView ivPicture2;
        private final ImageView ivPicture3;

        private final TextView tvTitle;
        private final TextView tvAuthor;

        public MyViewHolder3(@NonNull View itemView) {
            super(itemView);

            ivPicture1 = itemView.findViewById(R.id.iv_picture1);
            ivPicture2 = itemView.findViewById(R.id.iv_picture2);
            ivPicture3 = itemView.findViewById(R.id.iv_picture3);
            tvTitle = itemView.findViewById(R.id.tv_title);
            tvAuthor = itemView.findViewById(R.id.tv_author);
        }
    }

    public class AdViewHolder extends RecyclerView.ViewHolder {

        private final ImageView ivPicture;
        private final View ivClose;

        public AdViewHolder(@NonNull View itemView) {
            super(itemView);
            ivPicture = itemView.findViewById(R.id.iv_picture);
            ivClose = itemView.findViewById(R.id.tv_close);
        }
    }


}
代码语言:javascript
复制
package com.xlong.myapplication.recyclerview;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.xlong.myapplication.R;

import java.util.ArrayList;
/**
 * 实现不同的RecyclerView item样式
 */
public class ArticleMoreListActivity extends AppCompatActivity{

    private static final String TAG = "ArticleMoreListActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_article_more_list);


        //1:找到循环视图
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        //2:一维列表(竖向)
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);

        //3:为RecyclerView添加布局管理器
        recyclerView.setLayoutManager(layoutManager);

        //设置适配器
        ArticleMoreAdapter adapter = new ArticleMoreAdapter();

        //把数据先传给适配器
        ArrayList<Article> articles = createData();
        adapter.setArticles(articles);
        Log.i(TAG, "onCreate: article size =" + articles.size());

        //添加适配器
        recyclerView.setAdapter(adapter);

    }


    /**
     * 自己造一点数据给RecyclerView
     *
     * @return 返回一个存放20条数据的新闻列表
     */
    private ArrayList<Article> createData() {
        ArrayList<Article> articles = new ArrayList<>();
        articles.add(new Article("辽宁清原抽水蓄能电站最后一台定子吊装完成",
                "人民网-图片频道,供稿:人民资讯", R.drawable.ic_article_1));
        articles.add(new Article("通行时间再缩短!广湛高铁佛山站建设正式启动",
                "人民网-广东频道,供稿:人民资讯", R.drawable.ic_article_2));
        articles.add(new Article("19岁杭州帅小伙第一名,还有人抓到一只甲鱼!今早3000多人在钱塘江边,太欢乐了",
                "杭州网", R.drawable.ic_article_3));

        //两张照片的
        Article article4 = new Article("今日起“两江小渡”航线恢复正常运营",
                "上游新闻", R.drawable.ic_article_4);
        article4.setPicture2(R.drawable.ic_article_12);
        articles.add(article4);


        articles.add(new Article("中国太保小排球夏令营在漳州火热启航",
                "国际时事讲解", R.drawable.ic_article_5));
        articles.add(new Article("奋力推动民族地区高质量发展和现代化建设迈出新步伐",
                "当代先锋网", R.drawable.ic_article_6));

        //两张照片的
        Article article7 = new Article("相信青春的力量|写在我省2024年万名大学生志愿服务西部计划出征之际",
                "人民网-图片频道,供稿:人民资讯", R.drawable.ic_article_7);
        article7.setPicture2(R.drawable.ic_article_5);
        articles.add(article7);



        articles.add(new Article("量身定制“海外订单” 贵州汽车制造开拓国际市场",
                "当代先锋网", R.drawable.ic_article_8));
        articles.add(new Article("势不可挡……在这里,乡村振兴的新引擎正发出强劲动力",
                "鲁网", R.drawable.ic_article_9));
        articles.add(new Article("菏泽职业学院召开2024届毕业生第二轮就业核查工作部署会",
                "大众报业·齐鲁壹点", R.drawable.ic_article_10));
        articles.add(new Article("菏泽职业学院学前教育系(育中教育学院)斩获省级大赛一等奖",
                "西安快线", R.drawable.ic_article_11));


        //三张照片的
        Article article12 = new Article("菏泽职业学院一类教学大赛,二等奖+2!",
                "大众报业·齐鲁壹点", R.drawable.ic_article_12);
        article12.setPicture2(R.drawable.ic_article_3);
        article12.setPicture3(R.drawable.ic_article_16);
        articles.add(article12);



        articles.add(new Article("中央气象台停止对“格美”编号 湖南辽宁吉林等地仍有强降雨",
                "国际时事讲解", R.drawable.ic_article_13));
        articles.add(new Article("习水仙源镇:清凉山水引客来 消夏避暑人气足",
                "多彩贵州网", R.drawable.ic_article_14));
        articles.add(new Article("习水县寨坝镇:清凉避暑地 康养第二乡",
                "多彩贵州网", R.drawable.ic_article_15));
        articles.add(new Article("赤水市元厚镇:新品荔枝出山记",
                "人民网-图片频道,供稿:人民资讯", R.drawable.ic_article_16));
        articles.add(new Article("习水三岔河镇小小错车道 畅通出行暖民心",
                "湖南日报", R.drawable.ic_article_17));
        articles.add(new Article("习水土城镇社会实践活动丰富学生假期生活",
                "上海咨询", R.drawable.ic_article_18));
        articles.add(new Article("赤水建强“小站点”释放乡村振兴新动能",
                "福建新闻网,供稿:人民资讯", R.drawable.ic_article_19));
        articles.add(new Article("习水同民镇:火龙果喜丰收 果农笑开颜",
                "上游新闻,供稿:人民资讯", R.drawable.ic_article_20));


        //两张广告
        articles.add(5, new Article(true, R.drawable.bg_ad1));
        articles.add(10, new Article(true, R.drawable.bg_ad2));


        return articles;
    }

}

总结:整体执行流程

  1. ArticleMoreListActivity启动 → onCreate初始化页面和RecyclerView
  2. 调用createData生成 22 条模拟数据(含新闻和广告)。
  3. 适配器接收数据并通知RecyclerView更新。
  4. RecyclerView依次调用:
    • getItemCount → 确定展示 22 条数据。
    • 对每个位置(0-21):
      • getItemViewType → 判断布局类型。
      • onCreateViewHolder → 创建对应布局的ViewHolder
      • onBindViewHolder → 将数据绑定到控件,完成渲染。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 零:需求
  • 一、初始化阶段
  • 二、数据准备阶段(数据源创建与传递)
  • 三、RecyclerView 渲染阶段(核心流程)
    • 1. getItemCount():确定列表长度
    • 2. getItemViewType(int position):确定每条数据的布局类型
    • 3. onCreateViewHolder(ViewGroup parent, int viewType):创建布局对应的 ViewHolder
    • 4. onBindViewHolder(ViewHolder holder, int position)
  • 总结:整体执行流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档