在一个recyclerViews中实现多个视图 [英] Implementation of several views in one 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
}
...
}
稍后在onCreateViewHolder
和onBindViewHolder
中,您可以创建其他视图持有者,并将您拥有的数据绑定到这些视图持有者.
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
+ 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
}
}
这篇关于在一个recyclerViews中实现多个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!