View binding for menu files?

Viewed 3182

Is it possible to use View Binding (or Data Binding) in menu resources?

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.menu_main, menu)
    
    // search using ID - can this be replaced by view binding?
    val searchView = menu.findItem(R.id.menu_search).actionView as SearchView
}
3 Answers

In most cases, view binding replaces findViewById.

According to the documentations:

View binding is a feature that allows you to more easily write code that interacts with views. Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module.

Where in menus it uses findItem() and not findViewById() method.

Specific to View Binding with menu items with custom xml views, not Data Binding:

partial_menu_sample_view.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:layout_width="?actionBarSize"
    android:layout_height="?actionBarSize"
    android:clipToPadding="false"
    android:focusable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:contentDescription="@null"
        android:src="@drawable/ic_sample"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/textview_sample"
        android:visibility="gone"
        app:layout_constraintBottom_toTopOf="@id/guideline_horizontal_center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@id/guideline_vertical_center"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_sample.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

  <androidx.appcompat.widget.Toolbar 
    android:id="@+id/toolbar_sample"/>

</LinearLayout>

SampleActivity.kt

class SampleActivity() {

  lateinit var binding: ActivitySampleBinding
  var menuSampleViewBinding: PartialMenuSampleViewBinding? = null

  ...

  override fun onCreate() {
    super.onCreate()
    binding = ActivitySampleBinding.inflate(layoutInflater)
    setContentView(binding.root)
    // make sure to set the toolbar
    setSupportActionBar(binding.toolbarSample)
  }

  ...

  override fun onCreateOptionsMenu() {
      // inflate the menu to show on your toolbar
      // replace with your own menu xml
      binding.toolbarProduct.inflateMenu(R.menu.activity_sample)
      
      with(binding.toolbarProduct.menu) {
            findItem(R.id.menu_item_cart)?.actionView?.let {
                menuSampleViewBinding = PartialMenuSampleViewBinding.bind(it)
            }
            // handle other menu items here
      }
  }

  ...

  fun customFunction() {
      // use as needed
      menuSampleViewBinding?.textviewSample?.text = "1"
      menuSampleViewBinding?.root?.setOnClickListeners { /* add what you need */ } 
  }

}

Used this in a use case where there's a badge count on the menu item. Works fine.

At the moment, dataBinding is only for layout resources, not menu resources.

Related