Search code examples
androidkotlinepoxyepoxy-modelview

Simple TextView not showing in Airbnb Epoxy


Iam trying to show a simple text view using epoxy in a recyclerview but it does not appear. What could I be doing wrong.

I expected something like this

enter image description here

But I am getting this instead

enter image description here

//build.gradle
    implementation "com.airbnb.android:epoxy:4.3.1"
    kapt "com.airbnb.android:epoxy-processor:4.3.1"

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val rv= findViewById<RecyclerView>(R.id.main_recyclerview)
        rv.adapter= MyController().adapter
    }
}

activity_main.xml

<?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"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/main_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MyController.kt

class MyController : Typed2EpoxyController<List<String>,Boolean>() {
    override fun buildModels(data1: List<String>, data2: Boolean) {
        MyTextViewModel_().id(1).titleText("first title")
        MyTextViewModel_().id(2).titleText("second title")
        MyTextViewModel_().id(3).titleText("third title")
    }
}

MyTextViewModel.kt

@EpoxyModelClass(layout = R.layout.textview_row)
abstract class MyTextViewModel(): EpoxyModelWithHolder<VH>() {
    @EpoxyAttribute
    var titleText: String = "Default Title Text"

    override fun bind(holder: VH) {
        super.bind(holder)
        holder.titleTextView.text= titleText
    }
    class VH : EpoxyHolder() {
        lateinit var titleTextView: TextView
        override fun bindView(itemView: View) {
            titleTextView= itemView.findViewById(R.id.title)
        }
    }
}

textview_row.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView
        android:id="@+id/title_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:text="SIMPLE TITLE"
        app:layout_constraintBaseline_toBaselineOf="@+id/more_textview"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/more_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:text="More"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Solution

  • I have found multiple problems and solution is here:

    1 - First fix textview_row height as Ilya Gazman suggested

        <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <TextView
            android:id="@+id/title_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:text="SIMPLE TITLE"
            app:layout_constraintBaseline_toBaselineOf="@+id/more_textview"
            app:layout_constraintStart_toStartOf="parent" />
    
        <TextView
            android:id="@+id/more_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:text="More"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    2 - Problem with RecyclerView class type, you should use com.airbnb.epoxy.EpoxyRecyclerView

    <?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"
        tools:context=".MainActivity">
    
        <com.airbnb.epoxy.EpoxyRecyclerView
            android:id="@+id/main_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    3 - Controller initialisation

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val rv = findViewById<EpoxyRecyclerView>(R.id.main_recyclerview)
            val controller  = MyController()
            controller.setData(listOf("test","test2", "test3"),true)
            rv.adapter = controller.adapter
        }
    }
    

    4 - Controller addTo was missing

    class MyController : Typed2EpoxyController<List<String>,Boolean>() {
        override fun buildModels(data1: List<String>, data2: Boolean) {
           data1.forEachIndexed { index, s ->
               MyTextViewModel_().id(index).titleText(s).addTo(this)
           }
        }
    }
    

    5 - Wrong findViewById reference. From your example you were using title.

    @EpoxyModelClass(layout = R.layout.textview_row)
    abstract class MyTextViewModel(): EpoxyModelWithHolder<MyTextViewModel.VH>() {
        @EpoxyAttribute
        var titleText: String = "Default Title Text"
    
        override fun bind(holder: VH) {
            super.bind(holder)
            holder.titleTextView.text= titleText
        }
    
        class VH : EpoxyHolder() {
            lateinit var titleTextView: TextView
            override fun bindView(itemView: View) {
                titleTextView = itemView.findViewById(R.id.title_textview)
            }
        }
    } 
    

    Results:

    enter image description here