Search code examples
androidkotlinmenuitemmenubar

Edit focus of an item from the menu bar on click


I have a menu bar with three items, "home", "settings" and "progress". When I open the app, the home item is on focus, but when I click on another item, the focus stays on the home item unless I press twice on another item. Here is what it looks like on the first click and here is what it looks like when you press twice on the "settings" icon. I am trying to change the code so that when I select another item, the focus goes there from the first click and once an item is selected, you should see the filled icon, not the outlined one.

This is how an item looks in the menu xml file:

    <item
        android:id="@+id/settings"
        android:icon="@drawable/settings_selector"
        android:title="@string/settings" />

settings_selector.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/settingsfull" android:state_checked="true"/>
    <item android:drawable="@drawable/settingsoutlined" android:state_checked="false"/>

</selector>

Also, in the Settings Activity, this is the code that I added in the OnCreate function:

navigationView = findViewById(R.id.bottom_navigation)
        navigationView?.itemIconTintList = null
        navigationView?.setOnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.myhome -> {val i = Intent(this, UserDashboard::class.java)
                    startActivity(i)}
                R.id.settings -> {}
                R.id.progress -> {val i = Intent(this, Progress::class.java)
                    startActivity(i)}
            }
            true
        }

I have the same code for the other 2 items & their activities. I tried to add android:focusable="true" and android:focusableInTouchMode="true" in the xml file, but nothing happened, and since these items are not buttons or text views, I am not sure how to change this. I also changed the state_checked from the settings_selector, but again, it didn't solve my problem.

Thanks.


Solution

  • Somewhat tricky method is to use custom callback

    Outside of a class or a file used to store extensions

    fun <T : View> View.invokeSelectableState(state: (Boolean?) -> Unit): View {
        var clicks = 0
        setOnClickListener {
            //if(!isPressed) return@setOnClickListener
            clicks++
    
            when {
                clicks % 2 == 0 -> {
                    if(isSelected) {
                        isSelected = false
                        state(false)
                    }else if(!isSelected){
                        isSelected = true
                        state(true)
                    }
                }
                clicks % 2 != 0 -> {
                    if(isSelected) {
                        isSelected = false
                        state(false)
                    }else if(!isSelected){
                        isSelected = true
                        state(true)
                    }
                }
                else -> {
                    state(null)
                }
            }
    
    
        }
    
        return this as T
    
        //  setOnClickListener(onClick)
    
    
    
    }
    
    
    navigationView?.menu.apply {
       findItem(R.id.myhome).invokeSelectableState {
          if(state == false) return@invokeSelectableState
          findItem(R.id.settings).isSelected = false
          findItem(R.id.progress).isSelected = false
       }
       findItem(R.id.settings).invokeSelectableState {
          if(state == false) return@invokeSelectableState
          findItem(R.id.progress).isSelected = false
          findItem(R.id.myhome).isSelected = false
       findItem(R.id.progress).invokeSelectableState {
          if(state == false) return@invokeSelectableState
          findItem(R.id.myhome).isSelected = false
          findItem(R.id.settings).isSelected = false
       }
    }