最终实现的效果如下:
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、最后绑定适配器,大功告成!