August W. Gruneisen
August W. Gruneisen

Reputation: 227

How can I have multiple TextViews inside a RecyclerView list item

I know that RecyclerView lists are flexible and that it's possible to have multiple views in each item. I can't find any good example code that will help me implement this.

I am trying to implement a simple RecyclerView list with each list item as a custom .xml layout that I have created. What must be done in for the RecyclerView.Adapter to be able to access each different view by its ID from the custom layout file and be able to update each value?

I've basically copied the following code from Android Docs.

//ScannedDevicesListAdapter.kt

import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class ScannedDevicesListAdapter(private val myDataset: Array<String>) :
    RecyclerView.Adapter<ScannedDevicesListAdapter.ScannedDevicesListViewHolder>() {

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder.
    // Each data item is just a string in this case that is shown in a TextView.
    class ScannedDevicesListViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(parent: ViewGroup,
                                    viewType: Int): ScannedDevicesListAdapter.ScannedDevicesListViewHolder {
        // create a new view
        val textView = LayoutInflater.from(parent.context)
            .inflate(R.layout.scanned_devices_list_item, parent, false) as TextView
        // set the view's size, margins, paddings and layout parameters
        return ScannedDevicesListViewHolder(textView)
    }

    // Replace the contents of a view (invoked by the layout manager)
    override fun onBindViewHolder(holder: ScannedDevicesListViewHolder, position: Int) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.textView.text = myDataset[position]
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = myDataset.size
}

Here is the .xml file for my custom view:

Screenshot of the custom list item

//scanned_devices_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="30dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/TextView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            tools:text="Field 1" />

        <TextView
            android:id="@+id/TextView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            tools:text="Field 2" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/TextView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            tools:text="Field 3" />
    </LinearLayout>

</LinearLayout>

Upvotes: 1

Views: 1752

Answers (2)

jenil mangukiya
jenil mangukiya

Reputation: 1

You Can try this....

    class sel_cat_adapter(ctx: Context, list: MutableList<Any>) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private var ctx: Context = ctx
    private var list: MutableList<Any> = list
    private var ITEM = 0
    private var Ads = 1
    var ITEM_PER_Ad = 5

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {


        when (viewType) {
            ITEM -> {
                var inflater =
                    LayoutInflater.from(ctx).inflate(R.layout.customlayoutfor_sel_cat, null, false)
                return viewholderclass(inflater)
            }
            Ads -> {
                var inflater = LayoutInflater.from(ctx).inflate(R.layout.ads_banner, null, false)
                return AdsViewHolder(inflater)
            }
            else -> {
                var inflater = LayoutInflater.from(ctx).inflate(R.layout.ads_banner, null, false)
                return AdsViewHolder(inflater)
            }
        }
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        var viewtype = getItemViewType(position)
        when (viewtype) {
            ITEM -> {
                var myholder = holder as viewholderclass
            }
            Ads -> {
                var myholder = holder as AdsViewHolder
            }
            else -> {

            }
        }
        holder.itemView.setOnClickListener {
            if (viewtype == ITEM) {
               Toast.makeText(ctx, "Item", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(ctx, "Ads", Toast.LENGTH_LONG).show()
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        return if (position % ITEM_PER_Ad == 0) {
            if (list[position] is AdView) {
                Ads
            } else {
                ITEM
            }
        } else {
            ITEM
        }
    }

    class AdsViewHolder(itemview: View) : RecyclerView.ViewHolder(itemview){

    }


    class viewholderclass(itemview: View) : RecyclerView.ViewHolder(itemview) {


    }
}

Upvotes: 0

Anatolii
Anatolii

Reputation: 14660

You should change your ViewHolder implementation as it should take your parent View(from the xml file) as a parameter not a TextView. TextViews are subitems that can be defined as member variables in your ViewHolder:

import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class ScannedDevicesListAdapter(private val myDataset: Array<String>) :
    RecyclerView.Adapter<ScannedDevicesListAdapter.ScannedDevicesListViewHolder>() {

    class ScannedDevicesListViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
        val tv1 = view.TextView1
        val tv2 = view.TextView2
        val tv3 = view.TextView3
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(parent: ViewGroup,
                                viewType: Int): 
    ScannedDevicesListAdapter.ScannedDevicesListViewHolder {
        // create a new view
        val linearLayout = LayoutInflater.from(parent.context)
        .inflate(R.layout.scanned_devices_list_item, parent, false) as View
       // set the view's size, margins, paddings and layout parameters
       return ScannedDevicesListViewHolder(linearLayout)
    }

    override fun onBindViewHolder(holder: ScannedDevicesListViewHolder, position: Int) {
        holder.tv1.text = myDataset[position]
        // set your other views here
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = myDataset.size
}

Upvotes: 1

Related Questions