Challenge: An empty view for the RecyclerView

I made the recyclerview within a constrained layout… and inserted an (Invisible) imagebutton above it in the middle… all inside the same fragment_crime_list.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">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/crime_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="-130dp" />

    <ImageButton
        android:id="@+id/imageButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/crime_recycler_view"
        app:layout_constraintTop_toTopOf="@+id/crime_recycler_view"
        app:srcCompat="@drawable/ic_menu_add"
        android:visibility="invisible"/>


</androidx.constraintlayout.widget.ConstraintLayout>

inside the UpdateUI i set a condition if crimes.isEmpty()

 private fun updateUI(crimes: List<Crime>) {
    if (crimes.isEmpty()){
        imageButton = view?.findViewById(R.id.imageButton) as ImageButton
        imageButton.setVisibility(View.VISIBLE)
        imageButton.setOnClickListener{
                    val crime = Crime()
                    crimeListViewModel.addCrime(crime)
                    callbacks?.onCrimeSelected(crime.id)
        }
    } else{
        adapter = CrimeAdapter(crimes)
        crimeRecyclerView.adapter = adapter
    }

}
4 Likes

Looks clean.
However I don’t know why, but button disappears only when there are two crimes on the list.
When there is one crime, it is still visible.

what is your condition?

So this is my fragment_crime_list.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"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/crime_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <ImageButton
        android:id="@+id/button_add_crime"
        android:contentDescription="@string/new_crime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:srcCompat="@drawable/ic_menu_add"
        android:visibility="invisible"/>

    <TextView
        android:id="@+id/text_no_crimes"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="70dp"
        android:text="@string/no_crimes"
        android:visibility="invisible"/>

</androidx.constraintlayout.widget.ConstraintLayout>

and the CrimeListFragment.kt (updateUI method)

private fun updateUI(crimes: List<Crime>) {

        var addCrimeImageButton: ImageButton? = view?.findViewById(R.id.button_add_crime)
        var noCrimesTextView: TextView? = view?.findViewById(R.id.text_no_crimes)

        if (crimes.size == 0) {
            noCrimesTextView = view?.findViewById(R.id.text_no_crimes) as TextView
            noCrimesTextView.setVisibility(View.VISIBLE)

            addCrimeImageButton = view?.findViewById(R.id.button_add_crime) as ImageButton
            addCrimeImageButton.setVisibility(View.VISIBLE)
            addCrimeImageButton.setOnClickListener {
                val crime = Crime()
                crimeListViewModel.addCrime(crime)
                callbacks?.onCrimeSelected(crime.id)
            }
        } else {
            adapter = CrimeAdapter(crimes)
            crimeRecyclerView.adapter = adapter
        }
    }

Also tried with crimes.isEmpty() but result is the same.

you are setting these values as global values. and once you update them, their settings wont change back to be invisible automatically. you need to change them manually in the else branch.
or make their scope as local within the if branch.

Thank you, such a simple solution…
Maybe it is not too clean, but here is my updateUI method after changes:

private fun updateUI(crimes: List<Crime>) {

        var addCrimeImageButton: ImageButton? = view?.findViewById(R.id.button_add_crime)
        var noCrimesTextView: TextView? = view?.findViewById(R.id.text_no_crimes)

        if (crimes.size == 0) {
            noCrimesTextView = view?.findViewById(R.id.text_no_crimes) as TextView
            noCrimesTextView.setVisibility(View.VISIBLE)

            addCrimeImageButton = view?.findViewById(R.id.button_add_crime) as ImageButton
            addCrimeImageButton.setVisibility(View.VISIBLE)
            addCrimeImageButton.setOnClickListener {
                val crime = Crime()
                crimeListViewModel.addCrime(crime)
                callbacks?.onCrimeSelected(crime.id)
            }
        } else {
            noCrimesTextView = view?.findViewById(R.id.text_no_crimes) as TextView
            noCrimesTextView.setVisibility(View.INVISIBLE)
            addCrimeImageButton = view?.findViewById(R.id.button_add_crime) as ImageButton
            addCrimeImageButton.setVisibility(View.INVISIBLE)

            adapter = CrimeAdapter(crimes)
            crimeRecyclerView.adapter = adapter
        }
    }

well. since you have this here

no need to make the code messy here

keep them in their place where you define the properties all together…