首页用RecylerView实现两栏布局

最终实现的效果如下:

1、主窗口布局:

主窗口就是需要显示RecylerView数据的窗口,后端对应的是一个Fragment。布局如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/fragment_backgroupd"
    android:orientation="vertical"
    tools:context=".ui.index.IndexFragment">
<!--toolbar-->
    <include
        android:id="@+id/pubtoolbar"
        layout="@layout/apptoolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <!--RecyclerView标题-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp">
        <include android:id="@+id/grouptype"
            layout="@layout/banner_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </LinearLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/group_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginBottom="60dp"

            >
        </androidx.recyclerview.widget.RecyclerView>
    
</androidx.appcompat.widget.LinearLayoutCompat>

显示效果如下:

其中RecyclerView组件就是了我们要展现的两列容器,RecyclerView只是个容器,里面的数据布局需要通过子布局来展现。所以RecyclerView还包括一个子布局。子布局就是上面一个图片,下面一个标题,子布局名称为course_card.xml布局如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardBackgroundColor="@color/zhuti"
     >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="10dp">
        <ImageView
            android:id="@+id/img"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/item_backgroupd"
            android:layout_alignParentTop="true"/>

        <TextView
            android:id="@+id/txt"
            android:layout_width="match_parent"
            android:layout_height="20dp"
            android:layout_below="@+id/img"
            android:layout_alignParentBottom="true"
            android:gravity="center"
            android:text="dddddddddddd"/>
    </RelativeLayout>


</androidx.cardview.widget.CardView>

子布局效果如下:

通过子布局,可以知道,要展现的上面图片,下面是标题。下面我们需要将子布局、数据、RecylerView帮到一起。

3、数据生成:

首先是声明一个数据实体,可以将此数据绑定到子布局。可以设置图片、标题。为了省事,我们统一用一张默认图片,只需要用到标题。下面实体,我们只用属性name。

//课程
@JsonIgnoreProperties(ignoreUnknown = true) //反序列化时忽略未知属性
data class Course(
        val id:Int=0,
        val name:String="",//教程名称
        val url:String="",//教程地址
        val image:String="",//图片
        val cclass:String="",//分类
        val group_id:String=""//课程分组
) {
}

4、创建适配器,用来装载数据:

适配器继承自RecyclerView.Adapter,Adapter类是个泛型抽象类,泛型类型需要继承子ViewHolder,这个ViewHolder主要是用来初始化子布局的控件对象。

class RecylerViewAdapter(data: ArrayList<Course>) : RecyclerView.Adapter<RecylerViewAdapter.InnViewHolder>() {
    private var group_list: ArrayList<Course> = ArrayList<Course>()

    //子布局控件初始化
    class InnViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var imageView //list item图片
                : ImageView
        var textView //list item文字
                : TextView

        init {
            //创建子布局对象
            imageView = itemView.findViewById(R.id.img)
            textView = itemView.findViewById(R.id.txt)
        }
    }

    //完成子布局的初始化
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InnViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.course_card , parent, false)
        //赋值
        val holder = InnViewHolder(view)

        //item点击事件
        holder.itemView.setOnClickListener { v ->
            val position = holder.adapterPosition
            Toast.makeText(v.context, "$position----", Toast.LENGTH_SHORT).show()
        }
        holder.imageView.setOnClickListener { v -> //当前item
            val position = holder.adapterPosition
            Toast.makeText(v.context, group_list[position].name, Toast.LENGTH_SHORT).show()
        }
        holder.textView.setOnClickListener { v ->
            val position = holder.adapterPosition
            Toast.makeText(v.context, group_list[position].name, Toast.LENGTH_SHORT).show()
        }
        return holder
    }

    //子布局控件内容绑定
    override fun onBindViewHolder(holder: InnViewHolder, position: Int) {
        val resb: Course = group_list[position]
        Log.d(this.javaClass.toString(), resb.name.toString() + ">>>>")
        holder.textView.setText(resb.name)

    }

    override fun getItemCount(): Int {
        return group_list.size
    }

    init {
        group_list = data
        Log.d(this.javaClass.toString() + "初始化", data.size.toString() + "")
    }
}

来解释一下适配器的代码:

1、RecylerViewAdapter类接收一个参数,就是要加载的数据,这里是ArrayList<Course>。

2、RecylerViewAdapter继承自RecyclerView.Adapter,Adapter需要指定一个辅助类继承自ViewHolder。这里指定的是内部类:InnViewHolder。

3、内部类InnViewHolder实现,InnViewHolder 是初始化子布局的控件,所以需要将子布局对象course_card.xml传递给InnViewHolder。

4、onCreateViewHolder 函数:onCreateViewHolder函数根据屏幕的显示区域,创建合适数量的子布局对象。并为其控件创建监听事件。

5、onBindViewHolder 函数:绑定数据,创建一个子布局对象,就为其赋值。

通过上面的功能描述,可以知道,适配器是根据屏幕可见区域及滚动创建合适的子布局对象。所以创建、数据绑定的方法应该是出于屏幕滚动监听对象的一个循环中。每次滚动屏幕,根据可见区域高度来确定调用onCreateViewHolder、onBindViewHolder函数的次数。

5、使用RecyclerView将数据与适配器绑定:

Fragment的onCreateView函数代码如下:

   override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        var view=inflater.inflate(R.layout.index_fragment, container, false)

        //数组填充数据
        val data: ArrayList<Course> = ArrayList<Course>()
        for( x in 1..5){
            var course=Course(name = "rowxxxxxxxxxxx_ ${x}")
            data.add(course)
        }

        val recyclerView: RecyclerView =view.findViewById<RecyclerView>(R.id.group_list)
        var colums=2

        val mLayoutManager: RecyclerView.LayoutManager = StaggeredGridLayoutManager(
                colums, StaggeredGridLayoutManager.VERTICAL)
        //线性布局
//        val layoutManager = LinearLayoutManager(context)
//        recyclerView.layoutManager = layoutManager

        recyclerView.layoutManager = mLayoutManager

        val adapter = RecylerViewAdapter(data)
        recyclerView.adapter = adapter

        return view
    }

解释:

1、fragment窗口布局文件加载代码:
var view=inflater.inflate(R.layout.index_fragment, container, false)

加载后,就可以通过view,.findViewById获取RecyclerView控件了。

2、声明数据变量data,然后通过一个循环,生成5条course数据。

3、声明一个流式布局,StaggeredGridLayoutManager,也可以用网格布局。来管理RecyclerView内容。

4、最后绑定适配器,大功告成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT老卢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值