RecyclerView实现多种Item布局,如浏览器纵向的recyclerView会放不同类型的Item布局,效果图如下:
--------------本篇将以联系人界面为例来实现多种Item布局的RecyclerView--------------
-
RecyclerView实现多种Item布局
- 首先自行写一个Activity、RecyclerView布局和自定义Adapter,以及两个Item布局;
- 定义若干个ViewHolder,获取对应Item中的控件;
- 在自定义adapter中定义若干个常量作为多种Item布局的切换的入口;
- 重写RecyclerView的getItemViewType方法,根据返回的常量来标记对应的Item布局;
- 在Adapter重写的onCreateViewHolder方法中根据viewType类型绑定对应的Item布局,返回对应的ViewHolder;
- 在Adapter重写的onBindViewHolder方法中根据不同类型的holder绑定数据。
2. 定义ViewHolder
本示例实现两种不通类型的Item布局,因此需要自定义2个ViewHolder,在ViewHolder中根据Id去获取各自Item布局中的控件;
class FirstViewHolder(view : View) : RecyclerView.ViewHolder(view){
var contactImg1 : ImageView? = null
var contactName1 : TextView? = null
init{
contactImg1 = view.findViewById(R.id.contact_item_img)
contactName1 = view.findViewById(R.id.contact_item_name)
}
}
class SecViewHolder(view : View) : RecyclerView.ViewHolder(view){
var contactImg2 : ImageView? = null
var contactName2 : TextView? = null
init{
contactImg2 = view.findViewById(R.id.contact_item_img_2)
contactName2 = view.findViewById(R.id.contact_item_name_2)
}
}
3. 在自定义adapter中定义常量
这里定义常量主要是作为重写getItemViewType方法的判断条件,即哪种情况下显示哪种Item布局;
val FIRST_ITEM : Int = 1
val SEC_ITEM : Int = 2
4. 重写RecyclerView的getItemViewType方法
根据返回的常量来标记对应位置要显示的Item布局,如当添加Item的位置为3的倍数时使用第2种Item布局;
override fun getItemViewType(position: Int): Int {
if(position % 3 == 0){
return SEC_ITEM
}else{
return FIRST_ITEM
}
}
5. onCreateViewHolder方法中根据viewType类型绑定对应的ViewHolder;
根据参数viewType可以得知当前position应该放置哪种类型的Item布局,如,当viewType为FIRST_ITEM时,绑定item1的布局返回,否则绑定item2的布局返回;
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if(viewType == FIRST_ITEM){
return FirstViewHolder(LayoutInflater.from(context).inflate(R.layout.addressbook_contact_item_1, parent, false))
}else{
return SecViewHolder(LayoutInflater.from(context).inflate(R.layout.addressbook_contact_item_2, parent, false))
}
}
6. onBindViewHolder方法中根据不同类型的holder绑定数据
- kotlin语言写法:
(1)首先需要调用getItemViewType方法获取当前位置的Item类型;
(2)根据Item类型拿到对应ViewHolder,然后通过ViewHolder来更新对应类型Item中控件的数据显示;
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var mContactItem = mContactList[position]
val myViewType = getItemViewType(position)
when(myViewType){
FIRST_ITEM -> {
holder as FirstViewHolder
holder.contactImg1?.setImageResource(mContactItem.contactImgId)
holder.contactName1?.text = mContactItem.contactName
}
SEC_ITEM -> {
holder as SecViewHolder
holder.contactImg2?.setImageResource(mContactItem.contactImgId)
holder.contactName2?.text = mContactItem.contactName
}
}
}
- Java语言写法:
- Java的写法不需要调用getItemViewType方法来获取当前位置的Item类型,直接通过instanceof进行类型检查获取对应Item类型;
- 通过holder调Item中的控件之前,在holder实例前要写明是哪个ViewHolder类的实例。
if(holder instanceof FirstViewHolder) {
((FirstViewHolder)holder).contactName1?.setText(mContactItem.contactName);
}else{
((SecViewHolder)holder).contactName2?.setText(mContactItem.contactName);
}
---------------------自定义Adapter中的完整代码及效果图如下--------------------------
- recyclerView实现多种Item布局的效果图
- 完整代码
class AddressBookAdapter(val context : Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var mContactList = ArrayList<ContactItem>()
val FIRST_ITEM : Int = 1
val SEC_ITEM : Int = 2
public fun setContactList(contactList : ArrayList<ContactItem>){
this.mContactList = contactList
notifyDataSetChanged()
}
class FirstViewHolder(view : View) : RecyclerView.ViewHolder(view){
var contactImg1 : ImageView? = null
var contactName1 : TextView? = null
init{
contactImg1 = view.findViewById(R.id.contact_item_img)
contactName1 = view.findViewById(R.id.contact_item_name)
}
}
class SecViewHolder(view : View) : RecyclerView.ViewHolder(view){
var contactImg2 : ImageView? = null
var contactName2 : TextView? = null
init{
contactImg2 = view.findViewById(R.id.contact_item_img_2)
contactName2 = view.findViewById(R.id.contact_item_name_2)
}
}
override fun getItemViewType(position: Int): Int {
if(position % 3 == 0){
return SEC_ITEM
}else{
return FIRST_ITEM
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if(viewType == FIRST_ITEM){
return FirstViewHolder(LayoutInflater.from(context).inflate(R.layout.addressbook_contact_item_1, parent, false))
}else{
return SecViewHolder(LayoutInflater.from(context).inflate(R.layout.addressbook_contact_item_2, parent, false))
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var mContactItem = mContactList[position]
val myViewType = getItemViewType(position)
when(myViewType){
FIRST_ITEM -> {
holder as FirstViewHolder
holder.contactImg1?.setImageResource(mContactItem.contactImgId)
holder.contactName1?.text = mContactItem.contactName
}
SEC_ITEM -> {
holder as SecViewHolder
holder.contactImg2?.setImageResource(mContactItem.contactImgId)
holder.contactName2?.text = mContactItem.contactName
}
}
}
override fun getItemCount(): Int = mContactList.size
}
👀关注公众号:Android老皮!!!欢迎大家来找我探讨交流👀