使用Recyclerview实现多布局效果

        Android应用开发中Recyclerview的使用频率非常高,多布局是使用Recyclerview经常实现效果之一。这里简单介绍一下多布局的基本开发流程,实现一个简单的多布局效果。

        实现如下效果图:

效果图

一、创建数据类

        创建数据类,用以模拟多布局填充数据。文中数据类以布尔值作为标识判断是否是标题数据。

data class Types(
    /**
     * 是否标题
     */
    val isTitle: Boolean? = false,

    /**
     * 标题
     */
    val title: String? = null,

    /**
     * 图标
     */
    val icon: Int? = 0,

    /**
     * 名称
     */
    val name: String? = null
)

二、创建网格布局

        使用Recyclerview创建常见的网格布局,最后再以此为基础实现多布局效果。

布局

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

适配器

class MultiLayoutsAdapter(val data: MutableList<Types> /*数据集合*/) : 
    RecyclerView.Adapter<RecyclerView.ViewHolder>(){
  
    //视图持有,提供视图的引用。
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        //布局控件
    }
  
    //创建新视图
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        //引用item布局文件
    }

    //替换视图的内容
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        //从数据集合中获取元素替换视图内容
    }

    //返回数据集合的大小
    override fun getItemCount(): Int {
        //数据集合大小
    }
  
}

Activity

    //设置网格布局管理器
    val manager = GridLayoutManager(this, 4)
    recyclerView.layoutManager = manager
  
    //设置用于描述item的适配器
    val adapter = MultiLayoutsAdapter(loadData() /*数据集合*/)
    recyclerView.adapter = adapter

三、创建多布局视图

        分别创建“标题”,“内容”视图。

标题

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_title_shape"
        android:gravity="center"
        android:textColor="@color/white"
        android:textSize="13sp"
        android:textStyle="bold" />

内容

    <FrameLayout
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@drawable/bg_content_shape">

        <ImageView
            android:id="@+id/iv_content_icon"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="center"
            android:background="@drawable/bg_content_shape"
            android:src="@drawable/ic_tee" />

    </FrameLayout>

    <TextView
        android:id="@+id/tv_content_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:textColor="@color/black"
        android:textSize="13sp"
        android:textStyle="bold" />

四、修改适配器和Activity

        在创建好的网格布局适配器和Activity的基础上进行修改,最终实现多布局的效果。

适配器

class MultiLayoutsAdapter(val data: MutableList<Types> /*数据集合*/) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){
     
     //第一步,删除ViewHolder,分别创建标题和内容的视图持有TitleViewHolder、ContentViewHolder。
//    //视图持有,提供视图的引用
//    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
//        //布局控件
//    }
    
    //视图持有,提供标题视图的引用。
    class TitleViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val tvTitle: TextView

        init {
            tvTitle = view.findViewById(R.id.tv_title)
        }
    }

    //视图持有,提供内容视图的引用。
    class ContentViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val ivIcon: ImageView
        val tvName: TextView

        init {
            ivIcon = view.findViewById(R.id.iv_content_icon)
            tvName = view.findViewById(R.id.tv_content_name)
        }
    }
  
    //创建新视图
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    
        //第三步,创建新视图,根据标题或内容创建布局。
        return if (isTitle(viewType)) {
            val view =
                LayoutInflater.from(parent.context).inflate(R.layout.item_rlv_title, parent, false)
            TitleViewHolder(view)
        } else {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_rlv_content, parent, false)
            ContentViewHolder(view)
        }
        
    }

    //替换视图的内容
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    
        //第四步,判断持有类型,从数据集合中获取元素并用该元素替换视图的内容。
        if (holder is TitleViewHolder) {
            holder.tvTitle.text = data[position].title
        } else if (holder is ContentViewHolder) {
            holder.ivIcon.setImageResource(data[position].icon!!)
            holder.tvName.text = data[position].name
        }
        
    }

    //返回数据集合的大小
    override fun getItemCount(): Int {
    
        //第五步,返回数据集合大小。
        return data.size
        
    }
    
    //第二步,提供视图类型判断。
    //获取Item视图类型
    override fun getItemViewType(position: Int): Int {
        if (isTitle(position)) {
            return position
        }
        return 1
    }

    //判断是否是标题
    private fun isTitle(position: Int): Boolean {
        return data[position].isTitle == true
    }
  
}

Activity

    //设置网格布局管理器
    val manager = GridLayoutManager(this, 4)
    recyclerView.layoutManager = manager
    
    //关键代码
    //设置标题占多少个spanCount
    manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() {
        override fun getSpanSize(position: Int): Int {
            if (loadData()[position].isTitle == true) {
                return manager.spanCount
            }
            return 1
        }
    })
  
    //设置用于描述item的适配器
    val adapter = MultiLayoutsAdapter(loadData() /*数据集合*/)
    recyclerView.adapter = adapter

最后

        到此我们实现了一个非常简单的多布局类型案例,希望对你有所帮助。

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

合州刺史

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值