RecycleView
1 简介:
一个非常重要和常用的UI组件,在应用中以列表形式或网格形式展示大量数据,是一个可滑动的组件
优点:
- 可重用有限数量的视图元素
- 可快速更新变化的数据
2 制作一个简单的RecycleView
2.1 在文件中添加RecycleView组件
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/news_list0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/search"
>
</androidx.recyclerview.widget.RecyclerView>
2.2 为每一个item创建xml布局
例如:
news.item.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100sp"
android:orientation="vertical"
android:paddingBottom="20sp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="36sp"
android:text="title"
android:autoSizeTextType="uniform"
android:textStyle="bold"
android:paddingRight="50sp"></TextView>
<TextView
android:id="@+id/tvAuther"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" auther"></TextView>
</LinearLayout>
2.3 继承一个Adapter
Adapter:
负责提供数据和创建列表项视图
数据和视图的媒介
当数据发生变化时,管理数据的创建、更新、添加、删除
NewsAdapter
class NewsAdapter :RecyclerView.Adapter<NewsViewHolder>{
private val newsList: List<NewsItemBean>;
constructor(newsList:List<NewsItemBean>){
this.newsList = newsList;
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.news_item,parent,false);
return NewsViewHolder(view);
}
override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
val itemBean = newsList[position];
itemBean.title?.let {
holder.tvTitle.text = it;
}
itemBean.auther.let{
holder.tvAuther.text = it;
}
}
override fun getItemCount(): Int {
return newsList.size;
}
}
NewItemBean:
data class NewsItemBean(
/*
标题
*/
val title: String?,
/*
作者
*/
val auther: String?
)
2.4 继承RecycleView.ViewHolder
class NewsViewHolder : RecyclerView.ViewHolder {
var tvTitle:TextView
private set
var tvAuther:TextView
private set
constructor(view: View) :super(view){
tvTitle=view.findViewById(R.id.tvTitle)
tvAuther=view.findViewById(R.id.tvAuther)
}
}
2.5 在相应Acitivity的onCreat()中,获取RecycleView,并且为它设置Adapter和LayoutParams
//在对应activity的onCreate()方法中调用addRecycleView()
//…………
private fun addRecycleView(){
newsRecycleView = findViewById(R.id.news_list0);
newsAdapter = NewsAdapter(createNewsData());//创建了假数据
newsRecycleView?.adapter = newsAdapter
newsRecycleView?.layoutManager = LinearLayoutManager(this)
}
效果如下:
至此一个简单的RecycleView就做好了!!!❀
3 实现多种item布局
有时我们想要显示的列表中,不仅仅只有一种item布局,可能有多种布局。那么接下来我们看看如何改善成为一个包含多种item的RecycleView.
3.1 编写每一种布局的xml文件
例如:在上面程序的基础上,再添加一个news_item2.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200sp"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="36sp"
android:text="title"
android:textSize="28sp"
android:textStyle="bold"
android:paddingRight="50sp"
tools:ignore="end"
>
</TextView>
<ImageView
android:id="@+id/ivImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/role"
>
</ImageView>
</LinearLayout>
3.2.adapter的修改:
对于每个类型的item有type来标识、区分他们
-
重写getItemViewType()方法,传进来的是位置,传出是类型:具体逻辑根据需要完成:
override fun getItemViewType(position: Int): Int { return itemType_pos.get(position) //这里简单的自定义了个List记录类型,直接查表即可。(RecycleView的item的数量、类型排列是死的) }
-
修改onCreatViewHolder方法;
根据传进来的viewType去选择加载成哪一种item,并且返回哪一种ViewHolder;NewsViewHolder1和NewsViewHolder2都继承于ViewHolder,因此返回ViewHolder类型
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view: View return when (viewType) { ITEM_TYPE1 -> { view = LayoutInflater.from(parent.context).inflate(R.layout.news_item, parent, false) NewsViewHolder1(view) } ITEM_TYPE2 -> { view = LayoutInflater.from(parent.context).inflate(R.layout.news_item2, parent, false) NewsViewHolder2(view) } // 添加其他类型对应的 ViewHolder... else -> throw IllegalArgumentException("Invalid view type") } }
-
修改onBindViewHolder方法:
override fun onBindViewHolder(holder: ViewHolder, position: Int) { val newsItem = newsList[position] when (holder) { is NewsViewHolder1 -> holder.bindData(newsItem as NewsItemBeanWithAuther) // 如果是 NewsViewHolder 类型,调用其 bindData 方法 is NewsViewHolder2 -> holder.bindData(newsItem as NewsItemBeanWithImage) // 如果是 NewsViewHolder2 类型,调用其 bindData 方法 // 添加其他类型对应的 bindData 调用... } }
3.3.再新建一个NewsViewHolder2.kt类,用于处理第二种news_item2:
class NewsViewHolder2 : ViewHolder {
var tvTitle: TextView
private set
var ivImage: ImageView
private set
constructor(view: View) :super(view){
tvTitle=view.findViewById(R.id.tvTitle)
ivImage=view.findViewById(R.id.ivImage)
}
fun bindData(newsItemBeanWithImage: NewsItemBeanWithImage){
tvTitle.text = newsItemBeanWithImage.title
ivImage.setImageResource(newsItemBeanWithImage.imageUrl)
}
}
同样得再NewsViewHolder1中也添加一个bindData方法。