Android 如何使用不同类型的项目(文本视图、按钮、微调器)实现通用的RecyclerView?
我正在Kotlin开发一个Android应用程序,允许智能手机通过BLE与nRF52840通信以读取/写入数据 我正在开发显示此数据的视图。此视图以不同参数的形式出现,可以对其进行操作(使用按钮或微调器),也可以不操作(包含数据的简单TextView) 因此,我首先为每种类型的视图(带有TextView、Button或Spinner的参数)创建了一个RecyclerView activity.xml:Android 如何使用不同类型的项目(文本视图、按钮、微调器)实现通用的RecyclerView?,android,kotlin,android-recyclerview,Android,Kotlin,Android Recyclerview,我正在Kotlin开发一个Android应用程序,允许智能手机通过BLE与nRF52840通信以读取/写入数据 我正在开发显示此数据的视图。此视图以不同参数的形式出现,可以对其进行操作(使用按钮或微调器),也可以不操作(包含数据的简单TextView) 因此,我首先为每种类型的视图(带有TextView、Button或Spinner的参数)创建了一个RecyclerView activity.xml: <androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_parameters_text"
tools:listitem="@layout/parameter_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
app:layout_constraintTop_toBottomOf="@id/currentConnexion"
app:layout_constraintBottom_toTopOf="@+id/rv_parameters_spinner"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_parameters_spinner"
tools:listitem="@layout/parameter_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/rv_parameters_text"
app:layout_constraintBottom_toTopOf="@+id/rv_parameters_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_parameters_button"
tools:listitem="@layout/parameter_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/rv_parameters_spinner"
app:layout_constraintBottom_toTopOf="@+id/disconnect"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
您能帮助我吗?您需要创建自己的
RecyclerView.Adapter
,它将通过支持不同的视图类型来提供不同的视图持有者。备份适配器的数据将包含这些类型(文本、微调器、按钮),每个类型都有相应的ViewHolder
s
这是我快速输入的示例实现,目的是让您了解:
sealed class MyData {
data class Data1(val name: String)
data class Data2(val number: Int)
}
class CustomAdapter(private val dataSet: Array<MyData>) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
sealed class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class ViewHolder1(itemView: View) : ViewHolder(itemView) {
val textView: TextView
init {
textView = view.findViewById(R.id.textView1)
}
class ViewHolder2(itemView: View) : ViewHolder(itemView) {
val textView: TextView
init {
textView = view.findViewById(R.id.textView2)
}
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
if (viewType == 1) {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item1, viewGroup, false)
return ViewHolder1(view)
} else {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item2, viewGroup, false)
return ViewHolder2(view)
}
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
when (viewHolder) {
is ViewHolder1 -> viewHolder.textView = "${dataSet[position]}"
is ViewHolder2 -> viewHolder.textView = "${dataSet[position]}"
}
}
override fun getItemViewType(int position) = when (dataSet[position]) {
is MyData.Data1 -> 1
is MyData.Data2 -> 2
}
override fun getItemCount() = dataSet.size
}
密封类MyData{
数据类Data1(val名称:String)
数据类Data2(val编号:Int)
}
类CustomAdapter(专用val数据集:数组):
RecyclerView.Adapter(){
密封类ViewHolder(视图:视图):RecyclerView.ViewHolder(视图){
类ViewHolder1(项目视图:视图):ViewHolder(项目视图){
val textView:textView
初始化{
textView=view.findViewById(R.id.textView1)
}
类ViewHolder2(项目视图:视图):ViewHolder(项目视图){
val textView:textView
初始化{
textView=view.findViewById(R.id.textView2)
}
}
}
覆盖创建ViewHolder(viewGroup:viewGroup,viewType:Int):ViewHolder{
如果(viewType==1){
val view=LayoutInflater.from(viewGroup.context)
.充气(R.layout.text\u row\u item1,视图组,false)
返回视图保持器1(视图)
}否则{
val view=LayoutInflater.from(viewGroup.context)
.充气(R.layout.text\u row\u item2,视图组,false)
返回视图保持器2(视图)
}
}
覆盖BindViewHolder(viewHolder:viewHolder,位置:Int){
何时(视图持有者){
is ViewHolder1->viewHolder.textView=“${dataSet[position]}”
is ViewHolder2->viewHolder.textView=“${dataSet[position]}”
}
}
覆盖getItemViewType(int位置)=何时(数据集[位置]){
是MyData.Data1->1吗
是MyData.Data2->2吗
}
重写getItemCount()=dataSet.size
}
您需要创建自己的RecyclerView.Adapter
,它将通过支持不同的视图类型来提供不同的ViewHolder
。备份适配器的数据将包含这些类型(文本、微调器、按钮),并且您将为每种类型提供相应的ViewHolder
这是我快速输入的示例实现,目的是让您了解:
sealed class MyData {
data class Data1(val name: String)
data class Data2(val number: Int)
}
class CustomAdapter(private val dataSet: Array<MyData>) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
sealed class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class ViewHolder1(itemView: View) : ViewHolder(itemView) {
val textView: TextView
init {
textView = view.findViewById(R.id.textView1)
}
class ViewHolder2(itemView: View) : ViewHolder(itemView) {
val textView: TextView
init {
textView = view.findViewById(R.id.textView2)
}
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
if (viewType == 1) {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item1, viewGroup, false)
return ViewHolder1(view)
} else {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item2, viewGroup, false)
return ViewHolder2(view)
}
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
when (viewHolder) {
is ViewHolder1 -> viewHolder.textView = "${dataSet[position]}"
is ViewHolder2 -> viewHolder.textView = "${dataSet[position]}"
}
}
override fun getItemViewType(int position) = when (dataSet[position]) {
is MyData.Data1 -> 1
is MyData.Data2 -> 2
}
override fun getItemCount() = dataSet.size
}
密封类MyData{
数据类Data1(val名称:String)
数据类Data2(val编号:Int)
}
类CustomAdapter(专用val数据集:数组):
RecyclerView.Adapter(){
密封类ViewHolder(视图:视图):RecyclerView.ViewHolder(视图){
类ViewHolder1(项目视图:视图):ViewHolder(项目视图){
val textView:textView
初始化{
textView=view.findViewById(R.id.textView1)
}
类ViewHolder2(项目视图:视图):ViewHolder(项目视图){
val textView:textView
初始化{
textView=view.findViewById(R.id.textView2)
}
}
}
覆盖创建ViewHolder(viewGroup:viewGroup,viewType:Int):ViewHolder{
如果(viewType==1){
val view=LayoutInflater.from(viewGroup.context)
.充气(R.layout.text\u row\u item1,视图组,false)
返回视图保持器1(视图)
}否则{
val view=LayoutInflater.from(viewGroup.context)
.充气(R.layout.text\u row\u item2,视图组,false)
返回视图保持器2(视图)
}
}
覆盖BindViewHolder(viewHolder:viewHolder,位置:Int){
何时(视图持有者){
is ViewHolder1->viewHolder.textView=“${dataSet[position]}”
is ViewHolder2->viewHolder.textView=“${dataSet[position]}”
}
}
覆盖getItemViewType(int位置)=何时(数据集[位置]){
是MyData.Data1->1吗
是MyData.Data2->2吗
}
重写getItemCount()=dataSet.size
}
这可能不是最好的方法,但我编辑了updateValue函数,如下所示:
private fun updateValue(index: Int, value: ParameterText) {
parametersList.removeAt(index)
parametersList.insert(index, value)
rv_parameters.adapter?.notifyItemChanged(index)
}
这可能不是最好的方法,但我编辑了updateValue函数,如下所示:
private fun updateValue(index: Int, value: ParameterText) {
parametersList.removeAt(index)
parametersList.insert(index, value)
rv_parameters.adapter?.notifyItemChanged(index)
}
谢谢你的帮助!请看下面我的答案。谢谢你的帮助!请看下面我的答案。
// Adapter
private val parametersList = emptyDataSourceTyped<Any>()
private fun updateValue(index: Int, value: String) {
//parametersList[index].parameterValue = value
rv_parameters.adapter?.notifyDataSetChanged()
}
sealed class MyData {
data class Data1(val name: String)
data class Data2(val number: Int)
}
class CustomAdapter(private val dataSet: Array<MyData>) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
sealed class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class ViewHolder1(itemView: View) : ViewHolder(itemView) {
val textView: TextView
init {
textView = view.findViewById(R.id.textView1)
}
class ViewHolder2(itemView: View) : ViewHolder(itemView) {
val textView: TextView
init {
textView = view.findViewById(R.id.textView2)
}
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
if (viewType == 1) {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item1, viewGroup, false)
return ViewHolder1(view)
} else {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item2, viewGroup, false)
return ViewHolder2(view)
}
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
when (viewHolder) {
is ViewHolder1 -> viewHolder.textView = "${dataSet[position]}"
is ViewHolder2 -> viewHolder.textView = "${dataSet[position]}"
}
}
override fun getItemViewType(int position) = when (dataSet[position]) {
is MyData.Data1 -> 1
is MyData.Data2 -> 2
}
override fun getItemCount() = dataSet.size
}
private fun updateValue(index: Int, value: ParameterText) {
parametersList.removeAt(index)
parametersList.insert(index, value)
rv_parameters.adapter?.notifyItemChanged(index)
}