Search code examples
androidandroid-actionbarandroid-actionmodeandroid-cab

Show ActionMode over ActionMode


I have a list activity in which the user can do open action modes A and B. The user can also open action mode A then B on top of it.

The problem is that when action mode A is shown and action mode B is shown on top of it, A gets closed automatically when B is shown. The user can't navigate back from B to A.

I thought I could take note of action mode A visibility when action mode B is opened then restore it when action mode B is closed, but that doesn't work. It seems that it's not possible to immediately show another action mode after closing one. However this issue only happens if the action mode A is closed with the back arrow. When closed by code (ActionMode.finish()), action mode B can be shown, but the closing animation doesn't make it look like user is navigating back from B to A. So this solution is out of question.

So is there a way to open an action mode on top of another, or at least replace the menu layout of an action mode programatically then change it back?

Action mode A is actually the search action mode, from which the user can select results which opens action mode B if that can help to understand.


Solution

  • I think I reached desired behavior through postDelayed() from onDestroyActionMode of action mode B. This is not very elegant solution, but it works.

    My code snippet:

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            listView.onItemClickListener = AdapterView.OnItemClickListener { adapterView, view, p2, p3 ->
                startActionModeA()
                true
            }
        }
    
        var actionModeA: ActionMode? = null
    
        val actionModeCallbackA = object : ActionMode.Callback {
            override fun onActionItemClicked(mode: ActionMode?, p1: MenuItem?): Boolean {
                Log.wtf("ACTION MODE", "onActionItemClicked")
                actionModeB = startActionMode(actionModeCallbackB)
                return true
            }
    
            override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
                Log.wtf("ACTION MODE", "onCreateActionMode")
                val inflater = mode?.getMenuInflater()
                inflater?.inflate(R.menu.context_menu, menu)
                return true
            }
    
            override fun onPrepareActionMode(p0: ActionMode?, p1: Menu?): Boolean {
                Log.wtf("ACTION MODE", "onPrepareActionMode")
                return false
            }
    
            override fun onDestroyActionMode(p0: ActionMode?) {
                Log.wtf("ACTION MODE", "onDestroyActionMode")
                actionModeA = null
            }
    
    
        }
        var actionModeB: ActionMode? = null
    
        val actionModeCallbackB = object : ActionMode.Callback {
            override fun onActionItemClicked(mode: ActionMode?, p1: MenuItem?): Boolean {
                Log.wtf("ACTION MODE 2", "onActionItemClicked")
                return true
            }
    
            override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
                Log.wtf("ACTION MODE 2", "onCreateActionMode")
                val inflater = mode?.getMenuInflater()
                inflater?.inflate(R.menu.context_menu2, menu)
                return true
            }
    
            override fun onPrepareActionMode(p0: ActionMode?, p1: Menu?): Boolean {
                Log.wtf("ACTION MODE 2", "onPrepareActionMode")
                return false
            }
    
            override fun onDestroyActionMode(mode: ActionMode?) {
                Log.wtf("ACTION MODE 2", "onDestroyActionMode")
                actionModeB = null
                listView.postDelayed({
                    startActionModeA()
                }, 100)
            }
        }
    
        private fun startActionModeA() {
            actionModeA = startActionMode(actionModeCallbackA)
        }