Search code examples
androidkotlinandroid-recyclerviewandroid-drawable

Adding Drawable Images to RecyclerView


I'm trying to add drawable images to my menu RecyclerView, however when I run the app, the images don't show up. Do I need to make the menuImage in my model class an Int so it knows what position the image needs to go in? Or do I need to change my syntax when I'm adding it to the array? Or do I need to setImageDrawable on my menuImage in my MenuAdapter? Thank you!

My end result

enter image description here

What I have

enter image description here

menu_item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView 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="50dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/iconImageButton"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginStart="16dp"
            android:background="@drawable/circle_shape"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck" />

        <ImageView
            android:id="@+id/iconImageView"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:elevation="10dp"
            app:layout_constraintBottom_toBottomOf="@+id/iconImageButton"
            app:layout_constraintEnd_toEndOf="@+id/iconImageButton"
            app:layout_constraintStart_toStartOf="@+id/iconImageButton"
            app:layout_constraintTop_toTopOf="@+id/iconImageButton"
            app:srcCompat="@drawable/profile_photo_"
            android:contentDescription="@string/string_menu_icon_image" />

        <TextView
            android:id="@+id/menuLabelTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:text="@string/menu_label"
            android:textAllCaps="false"
            android:textColor="@color/black"
            android:textSize="16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/iconImageButton"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/menuArrowImageView"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_marginEnd="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/right_chevron_"
            android:contentDescription="@string/menu_arrow" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

MenuItem.kt

class MenuItem(val menuName: String = "", val menuImage: String = "")

MenuAdapter.kt

class MenuAdapter(var context: Context, var list: ArrayList<MenuItem>) : RecyclerView.Adapter<MenuAdapter.MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val v = LayoutInflater.from(parent?.context).inflate(R.layout.menu_item, parent, false)
        return MyViewHolder(v)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder?.bindItems(list[position])
    }

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

    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){

        fun bindItems(items: MenuItem) {
            val menuName = itemView.findViewById<TextView>(R.id.menuLabelTextView)
            val menuImage = itemView.findViewById<ImageView>(R.id.iconImageView)

            menuName.text = items.menuName
            Picasso.get().load(items.menuImage).into(menuImage)
        }
    }
}

MenuActivity.kt

lateinit var menuAdapter: MenuAdapter
val menuList = ArrayList<MenuItem>()

private fun createMenu() {

   menuAdapter = MenuAdapter(this, menuList)

  val menuRecycleView = findViewById<RecyclerView>(R.id.menuRecyclerView)
  menuRecycleView.apply {
       layoutManager = LinearLayoutManager(this@MenuActivity, LinearLayoutManager.VERTICAL, false)
       adapter = menuAdapter
       setHasFixedSize(true)
  }

  menuList.add(MenuItem("My Profile", "${R.drawable.outline_person_}"))
  menuList.add(MenuItem("My Bookings", "${R.drawable.bookings_}"))
  menuList.add(MenuItem("Payments", "${R.drawable.payment_}"))
  menuList.add(MenuItem("On Going Jobs", "${R.drawable.on_going_jobs_}"))
  menuList.add(MenuItem("Settings", "${R.drawable.settings_}"))
}

Solution

  • You're calling load(String) with a String, which is this method:

    Start an image request using the specified path. This is a convenience method for calling load(Uri). This path may be a remote URL, file resource (prefixed with file:), content resource (prefixed with content:), or android resource (prefixed with android.resource:).

    You're just passing the bare resource ID int, as a string:

    MenuItem("My Profile", "${R.drawable.outline_person_}")
    

    I don't know what it wants specifically, it could be "android.resource:${R.drawable.outline_person_}" (the int) or it might be "android.resource:R.drawable.outline_person_" (the qualified ID name) - I'd guess the first one, but try the other if it doesn't work.

    Your other option is using load(int) which takes the actual resource ID int directly, so you'd define items as MenuItem("My Profile", R.drawable.outline_person_) - this is way better IMO, unless you really need it as a string for some reason (and you can't just convert it to a string when you need it).

    I don't know if using app:srcCompat would be a problem, but you can try android:src instead if you're still seeing issues

    (There should be some error info about this in your logs btw, a message from Picasso saying "couldn't load URL 1234567 or whatever", always check the logs for hints!)