在一个recyclerViews中实现多个视图 [英] Implementation of several views in one recyclerViews

查看:78
本文介绍了在一个recyclerViews中实现多个视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Kotlin的一个recyclerViews中实现不同的视图?

我想创建一个包含法律代码的应用程序.我的问题是个别法律条款分为几章.而且,如果我可以创建一个可以显示所有食谱的程序,那么我真的不知道如何将其放入带有特定法律规定的版面配置以及有关本章编号和标题的信息之间的recyclerView中.

下面的代码仍然显示相同的视图.

package pl.nynacode.naukapraw
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.cart_view_legal_name.view.*
import kotlinx.android.synthetic.main.chapter_layout.view.*

class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>(){
    class MyViewHolder(val view: View, val view2: View):RecyclerView.ViewHolder(view) {

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val layoutInflater= LayoutInflater.from(parent.context);
        val legalName = layoutInflater.inflate(R.layout.cart_view_legal_name, parent ,false);
        val chapterName = layoutInflater.inflate(R.layout.chapter_layout, parent,false);
        return MyViewHolder(legalName, chapterName);
    }

    override fun getItemCount(): Int {
        return KodeksKarny.nrArticle.size;
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        when(position){
            0->{
                val chapter = holder.view2.tvChapterName;
                chapter.setText(KodeksKarny.nrArticle[position])
            }
            else->{
                val nrArticle = holder.view.nrArt;
                val textArticle=holder.view.txtArt;

                nrArticle.setText(KodeksKarny.nrArticle[position]);
                textArticle.setText(KodeksKarny.txtArticle[position]);

                // obsługa klikniecia na przycisk
                nrArticle.setOnClickListener{
                    if (textArticle.visibility == View.GONE){
                        textArticle.visibility = View.VISIBLE
                    }else textArticle.visibility = View.GONE
                }
            }
        }

    }
}

我要补充一点,我是一个初学者,但是我还不能做很多事情

解决方案

RecyclerView.Adapter具有称为fun getItemViewType(position: Int): Int的方法,该方法返回给定位置上的视图类型.

基于该功能,您可以创建不同的视图持有人,或将不同的布局传递给同一视图持有人(但要避免使用最后一个).

您只需要重写适配器中的功能并确定该位置的项目类型即可:

override fun getItemViewType(position: Int): Int {
    val item = getItem(position)
    // the code below is just an example. 
    val type = when (item) {
        is Header -> HEADER_TYPE
        is NotHeader -> NOT_HEADER_TYPE
    }
    return type
}

您可以在哪里定义这些类型?例如,在随播对象中:

class YourAdapter: ... {
    companion object {
        private const val HEADER_TYPE = 0
        private const val NOT_HEADER_TYPE = 1
    }

    ...
}

稍后在onCreateViewHolderonBindViewHolder中,您可以创建其他视图持有者,并将您拥有的数据绑定到这些视图持有者.

class YourAdapter: ... {
    companion object {
        private const val HEADER_TYPE = 0
        private const val NOT_HEADER_TYPE = 1
    }

    ...
    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)
        // the code below is just an example. 
        val type = when (item) {
            is Header -> HEADER_TYPE
            is NotHeader -> NOT_HEADER_TYPE
        }
        return type
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        if (viewType == HEADER_TYPE) {
            // Here you create HeaderViewHolder
        } else {
            val layoutInflater= LayoutInflater.from(parent.context);
            val legalName = layoutInflater.inflate(R.layout.cart_view_legal_name, parent ,false);
            val chapterName = layoutInflater.inflate(R.layout.chapter_layout, parent,false);
            return MyViewHolder(legalName, chapterName);
        }
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val itemViewType = getItemViewType(position)
        if (itemViewType == HEADER_TYPE) {
            // cast MyViewHolder to HeaderViewHolder, for example
            val header = viewHolder as HeaderViewHolder
            header.headerTitle.text = ...
        } else {
            val nrArticle = holder.view.nrArt;
            ... other type
        }

    }
}

此处是官方教程如何创建具有不同类型的视图的适配器.

我个人更喜欢实现abstract class BaseViewHolder: RecyclerView.ViewHolder,它将用作适配器实现的通用类型参数.此BaseViewHolder应该具有一个抽象方法,例如abstract fun bind(data: YourDataType).该功能将由扩展BaseViewHolder类的视图持有者实现.

此外,由于Kotlin为我们提供了密封类,因此我更喜欢创建一个密封类和从其扩展的对象以容纳视图持有者类型,因此当您实现onCreateViewHolder方法时,可以避免else情况.但这就是我所喜欢的,并且不需要任何方式.

sealed class + object s + onCreateViewHolder的示例:

sealed class Types(val rawType: Int) {
    object Header: Types(0)
    object NotHeader: Types(1)

    companion object {
       fun from(rawType: Int) = 
           when (rawType) {
               Header.rawType -> Header
               NotHeader.rawType -> NotHeader
               else -> throw RuntimeException("No such type")
           }
    }
}

class YourAdapter ... {

    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)
        // the code below is just an example. 
        val type = when (item) {
            is Header -> Types.Header.rawType
            is NotHeader -> Types.NotHeader.rawType
        }
        return type
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder =
        when (Types.from(viewType)) {
            is Types.Header -> // return HeaderViewHolder
            is Types.NotHeader -> // return NotHeaderViewHolder
        }
}

How can I implement different views in one recyclerViews in Kotlin ???

I want to create an application containing legal codes. My problem is that individual legal provisions are divided into chapters. And if I can create a progran that will display all the recipes for me, I don't really know how to put it in the recyclerView between the layout with specific legal provisions layout with information about the number and title of the chapter.

The code below still shows me the same view.

package pl.nynacode.naukapraw
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.cart_view_legal_name.view.*
import kotlinx.android.synthetic.main.chapter_layout.view.*

class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>(){
    class MyViewHolder(val view: View, val view2: View):RecyclerView.ViewHolder(view) {

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val layoutInflater= LayoutInflater.from(parent.context);
        val legalName = layoutInflater.inflate(R.layout.cart_view_legal_name, parent ,false);
        val chapterName = layoutInflater.inflate(R.layout.chapter_layout, parent,false);
        return MyViewHolder(legalName, chapterName);
    }

    override fun getItemCount(): Int {
        return KodeksKarny.nrArticle.size;
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        when(position){
            0->{
                val chapter = holder.view2.tvChapterName;
                chapter.setText(KodeksKarny.nrArticle[position])
            }
            else->{
                val nrArticle = holder.view.nrArt;
                val textArticle=holder.view.txtArt;

                nrArticle.setText(KodeksKarny.nrArticle[position]);
                textArticle.setText(KodeksKarny.txtArticle[position]);

                // obsługa klikniecia na przycisk
                nrArticle.setOnClickListener{
                    if (textArticle.visibility == View.GONE){
                        textArticle.visibility = View.VISIBLE
                    }else textArticle.visibility = View.GONE
                }
            }
        }

    }
}

I will add that I'm a beginner and I can't do much yet

解决方案

RecyclerView.Adapter has a method called fun getItemViewType(position: Int): Int that returns the type of view on a given position.

Based on that function you can create different view holders or pass to the same view holder type different layouts (but avoid last one).

You simply need to override a function in your adapter and decide the type of an item at that position:

override fun getItemViewType(position: Int): Int {
    val item = getItem(position)
    // the code below is just an example. 
    val type = when (item) {
        is Header -> HEADER_TYPE
        is NotHeader -> NOT_HEADER_TYPE
    }
    return type
}

Where you could define these types? In companion object for example:

class YourAdapter: ... {
    companion object {
        private const val HEADER_TYPE = 0
        private const val NOT_HEADER_TYPE = 1
    }

    ...
}

Later in onCreateViewHolder and onBindViewHolder you can create different view holders and bind to those view holders the data you have.

class YourAdapter: ... {
    companion object {
        private const val HEADER_TYPE = 0
        private const val NOT_HEADER_TYPE = 1
    }

    ...
    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)
        // the code below is just an example. 
        val type = when (item) {
            is Header -> HEADER_TYPE
            is NotHeader -> NOT_HEADER_TYPE
        }
        return type
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        if (viewType == HEADER_TYPE) {
            // Here you create HeaderViewHolder
        } else {
            val layoutInflater= LayoutInflater.from(parent.context);
            val legalName = layoutInflater.inflate(R.layout.cart_view_legal_name, parent ,false);
            val chapterName = layoutInflater.inflate(R.layout.chapter_layout, parent,false);
            return MyViewHolder(legalName, chapterName);
        }
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val itemViewType = getItemViewType(position)
        if (itemViewType == HEADER_TYPE) {
            // cast MyViewHolder to HeaderViewHolder, for example
            val header = viewHolder as HeaderViewHolder
            header.headerTitle.text = ...
        } else {
            val nrArticle = holder.view.nrArt;
            ... other type
        }

    }
}

Here are the official tutorials on how to create an adapter with different types of views.

What I personally prefer is to implement abstract class BaseViewHolder: RecyclerView.ViewHolder that will be used as a generic type argument of your adapter implementation. This BaseViewHolder should have an abstract method, like abstract fun bind(data: YourDataType). The function will be implemented by view holders that will extend the BaseViewHolder class.

Also, as Kotlin provides us with sealed classes I prefer to create a sealed class and objects that extend from it to hold view holder types so when you implement your onCreateViewHolder method it could avoid else case. But that is just what I like and is not required in any way.

An example of sealed class + objects + onCreateViewHolder:

sealed class Types(val rawType: Int) {
    object Header: Types(0)
    object NotHeader: Types(1)

    companion object {
       fun from(rawType: Int) = 
           when (rawType) {
               Header.rawType -> Header
               NotHeader.rawType -> NotHeader
               else -> throw RuntimeException("No such type")
           }
    }
}

class YourAdapter ... {

    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)
        // the code below is just an example. 
        val type = when (item) {
            is Header -> Types.Header.rawType
            is NotHeader -> Types.NotHeader.rawType
        }
        return type
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder =
        when (Types.from(viewType)) {
            is Types.Header -> // return HeaderViewHolder
            is Types.NotHeader -> // return NotHeaderViewHolder
        }
}

这篇关于在一个recyclerViews中实现多个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆