Hopefully a simple Kotlin regarding looping through a recycler

Viewed 71

I have a recycler in my activity for acrostic poetry. The recycler displays an image of the letters of the word (Stone Age, in this case) and an EditText to enter the acrostic words. What I want to do is read the words that have been entered, so for "Stone Age" I'm creating 8 items in the recycler.

In order to get the words, I have tried to replicate the steps in this question How to iterate over RecyclerView items. I think I'm close, but I can't quite get over the line.

I have this function where I am trying to read the values (at this stage just into the logcat)

I figured that getChildCount returned the items, but this is logging 2 (or sometimes, oddly, 3) rather than the 8 I would expect, so I'm struggling to understand what I am looping.

private fun saveTask() {
  var p: String = ""
  Log.d(HWG.TAG, "Children: ${acrosticRecycler.getChildCount().toString()}")

  for (i in 0 until acrosticRecycler.getChildCount()) {
    var holder: AcrosticAdapter.ViewHolder
    if(acrosticRecycler.findViewHolderForAdapterPosition(i) != null) {
        holder = acrosticRecycler.findViewHolderForAdapterPosition(i) as AcrosticAdapter.ViewHolder
        p = holder.txtWord.text.toString()
        Log.d(HWG.TAG, "Word: ${p}")
    }

  }
}

This is the layout of the recycler

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginRight="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginBottom="4dp"
    app:cardCornerRadius="4dp"
    app:cardElevation="6dp">

    <LinearLayout
        android:id="@+id/llTaskList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <ImageView
            android:id="@+id/imgLetter"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_gravity="center_vertical"
            android:adjustViewBounds="true"
            android:cropToPadding="true"
            android:scaleType="centerCrop"
            app:srcCompat="@drawable/icons8_s" />

        <EditText
            android:id="@+id/txtWord"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginStart="5dp"
            android:layout_marginLeft="5dp"
            android:hint="Stone Age"
            android:textAllCaps="true"
            android:textSize="18sp"
            android:textStyle="bold" />

    </LinearLayout>
</androidx.cardview.widget.CardView>

This is the activity in which the recycler sits

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/background"
    tools:context=".TextualTask">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="24dp"
        android:background="@color/background"
        app:cardCornerRadius="4dp"
        app:cardElevation="6dp"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="24dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="5dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="5dp">

                <ImageView
                    android:id="@+id/subjectImage"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_gravity="center_horizontal"
                    android:adjustViewBounds="true"
                    android:cropToPadding="true"
                    android:scaleType="centerCrop"
                    app:srcCompat="@drawable/icons8_knowledge_sharing_80" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    android:padding="5dp">

                    <TextView
                        android:id="@+id/txtTitle"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_marginStart="10dp"
                        android:layout_marginLeft="15dp"
                        android:text="Acrostic Poem"
                        android:textAllCaps="true"
                        android:textSize="16sp"
                        android:textStyle="bold" />

                </LinearLayout>

            </LinearLayout>

            <View
                android:id="@+id/divider"
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:layout_margin="6dp"
                android:background="?android:attr/listDivider" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="5dp">

                <TextView
                    android:id="@+id/txtPreamble"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginLeft="15dp"
                    android:text="Preamble text"
                    android:textAlignment="center"
                    android:textSize="14sp"
                    android:textStyle="bold|italic" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="5dp">

                <androidx.cardview.widget.CardView
                    android:id="@+id/crdWord"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="24dp"
                    app:cardBackgroundColor="@color/cardback"
                    app:cardCornerRadius="4dp"
                    app:cardElevation="6dp">

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:padding="5dp">

                        <Button
                            android:id="@+id/btnSubmit"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_margin="6dp"
                            android:backgroundTint="@color/start"
                            android:text="Submit" />

                        <androidx.recyclerview.widget.RecyclerView
                            android:id="@+id/acrosticRecycler"
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            tools:itemCount="5"
                            tools:listitem="@layout/acrostic_task" />
                       
                    </LinearLayout>

                </androidx.cardview.widget.CardView>
            </LinearLayout>
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

Oddly enough, sometime the for loop gets the values from items 0-2, but sometimes it doesn't. The call to saveTask is made from btnSubmit as I don't need to get the values at the point the user enters them, just when they're happy to submit.

Could someone point me in the right direction please?

1 Answers

You can't get the correct count from acrosticRecycler.getChildCount().

because acrosticRecycler.getChildCount() will return the count of currently showed item in the RecyclerView. So even if your data is 8, but the showed data in the screen is only 3 items. So you will always get 3 not 8.

It's not good practice to get the data from the ViewHolder in recycler view directly. You should get the data from the list you have inserted to recycler view adapter.

for example, you can create adapter like this :

class AcrosticAdapter(var listData: ArrayList<AcrosticPoetry>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun getItemCount(): Int = listData.size

}

//assuming this is your model class
class AcrosticPoetry() {
    var textWord = ""
}

and you can change your code to

private fun saveTask() {
  val adapter = acrosticRecycler.adapter as AcrosticAdapter
  val data = adapter.listData

  for (i in 0 until data.size) {
     val word = data[i].txtWord
     Log.d(HWG.TAG, "Word: ${word}")
  }
}
Related