1

I am trying to show a popup menu for the items in my RecyclerView: enter image description here

All the code samples on how to do this that I found online either use Java or when they in rare cases do use Kotlin, it's done without data binding.

Anyway what I'm trying to achieve is this:

<ImageButton
    android:id="@+id/options"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="14dp"
    android:layout_marginEnd="16dp"
    android:background="?attr/selectableItemBackground"
    android:contentDescription="@string/desc_options"
    android:onClickListener="@{(v) -> holder.test1.invoke()}"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@drawable/ic_more_vert" />

And in my RowHolder I have the following code:

class AgendaRowHolder(
    private val binding: AgendaRowBinding,
    val onRowClick: (AgendaModel) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
    fun bind(model: AgendaModel) {
        binding.model = model
        binding.holder = this
        binding.executePendingBindings()
    }

    fun test1() {
        // do something here
    }
}

However this will not compile at all and a workaround to solving this problem is to have a function as a property of the AgendaRowHolder class, but this approach doesn't work since I also have to pass the ImageView for the popup menu to know where to show up. So I used this alternative approach, namely adding an onClickListener in the bind() function:

fun bind(model: AgendaModel) {
    binding.model = model
    binding.holder = this
    binding.executePendingBindings()

    binding.options.setOnClickListener { showPopup(it) }
}

private fun showPopup(view : View) {
    val popup = PopupMenu(view.context, view)
    popup.setOnMenuItemClickListener { item ->
        when (item.itemId) {
            R.id.delete -> {
                AgendaRepository.delete(binding.model!!)
                true
            } else -> false
        }
    }
    val inflater: MenuInflater = popup.menuInflater
    inflater.inflate(R.menu.actions_agenda, popup.menu)
    popup.show()
}

This approach "works" in that it will show a popup menu and allow me to delete items, but I have a new problem here in that when an item/row gets delete it doesn't show up until the view is recreated, right now I'm not observing my data so that might be the reason as to why, but what I'm wondering is what would be the best approach to achieve this? Note: another thing that I tried is adding an android:onClick attribute in the xml and trying to handle this in the MainActivity, but I'm not sure which approach to take here. Can the first one be achieved? Ideally, I'd have:

android:onClickListener="@{(v) -> holder.showPopup.invoke(model, v)}" and then that showPopup function in the ViewHolder.

ulrich201
  • 75
  • 5

0 Answers0