[Android] Use ActionMode in Kotlin

ActionMode


The ActionMode mode is to generate a floating control similar to the ActionBar on the page, floating above the ActionBar, which can increase the function entry without occupying the page space. ActionMode has two modes

  1. Primary Action: The control overlay appears on the upper ActionBar
  2. Floating Action: The control floats around any View
Primary Action Floating Action

Start method


startActionModeStart by the method of Activity or View , and accept two parameters: ActionMode.CallbackActionMode.Type

public ActionMode startActionMode(android.view.ActionMode.Callback callback, int type)

ActionMode.Callback defines the life cycle callback of ActionMode:

public interface Callback {
    
    
    // AcionMode创建
    boolean onCreateActionMode(ActionMode var1, Menu var2);

    // AcionMode状态变化时(无效、或者项目更新)
    boolean onPrepareActionMode(ActionMode var1, Menu var2);

    // AcionMode菜单项被选中时
    boolean onActionItemClicked(ActionMode var1, MenuItem var2);

    // AcionMode销毁
    void onDestroyActionMode(ActionMode var1);
}

ActionMode.Type defines the two ActionMode types introduced earlier

public abstract class ActionMode {
    
    
    public static final int TYPE_FLOATING = 1;
    public static final int TYPE_PRIMARY = 0;}

Encapsulate ActionModeController


We encapsulate the ActionModeController class to simplify the ActionMode experience

class ActionModeController(
    // menu的resId
    @MenuRes private val resId: Int,
    // ActionMode 类型
    private val type: Int,
    // menu选择后回调
    private val onAction : (MenuItem) -> Unit
) {
    
    
    // 从Activiy启动
    fun startActionMode(activity: Activity) {
    
    
        activity.startActionMode(createActionModeCallback(), type)
    }

    // 从View启动
    fun startActionMode(view: View) {
    
    
        view.startActionMode(createActionModeCallback(), type)
    }

    private fun createActionModeCallback(): ActionMode.Callback {
    
    
        return object: ActionMode.Callback {
    
    
            override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
    
    
                mode.menuInflater.inflate(resId, menu)
                return true
            }

            override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
    
    
                return false
            }

            override fun onDestroyActionMode(mode: ActionMode) {
    
    
            }

            override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
    
    
                onAction.invoke(item)

                mode.finish()
                return true
            }
        }
    }
}

Next, take a look at the actual use effect

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/first"
        android:title="@string/first"
        android:icon="@drawable/ic_done"
        />

    <item
        android:id="@+id/second"
        android:title="@string/second"
        android:icon="@drawable/ic_close"
        />
</menu>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    tools:context=".MainFragment"
    android:orientation="vertical">

        <Button
            android:id="@+id/primary_action_mode_activity_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="PRIMARY ACTION MODE (ACTIVITY)"/>

        <Button
            android:id="@+id/primary_action_mode_view_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="PRIMARY ACTION MODE (VIEW)"/>

        <Button
            android:id="@+id/floating_action_mode_activity_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="FLOATING ACTION MODE (ACTIVITY)"/>

        <Button
            android:id="@+id/floating_action_mode_view_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="FLOATING ACTION MODE (VIEW)"/>
</LinearLayout>

class MainFragment : Fragment(R.layout.fragment_main) {
    
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    
    
        super.onViewCreated(view, savedInstanceState)

		// Primary Action
        val primaryActionModeController = ActionModeController(R.menu.action_menus, ActionMode.TYPE_PRIMARY) {
    
    

            when (it.itemId) {
    
    
                R.id.first -> {
    
    
                    Toast.makeText(context, "FIRST", Toast.LENGTH_SHORT).show()
                }
                R.id.second -> {
    
    
                    Toast.makeText(context, "SECOND", Toast.LENGTH_SHORT).show()
                }
            }
        }

        // Floating Action 
        val floatingActionModeController = ActionModeController(R.menu.action_menus, ActionMode.TYPE_FLOATING) {
    
    
            when (it.itemId) {
    
    
                R.id.first -> {
    
    
                    Toast.makeText(context, "FIRST", Toast.LENGTH_SHORT).show()
                }
                R.id.second -> {
    
    
                    Toast.makeText(context, "SECOND", Toast.LENGTH_SHORT).show()
                }
            }
        }

        // Activity 启动 Primary Action
        primary_action_mode_activity_button.setOnClickListener {
    
    
            primaryActionModeController.startActionMode(requireActivity())
        }

        // View 启动 Primary Action
        primary_action_mode_view_button.setOnClickListener {
    
    
            primaryActionModeController.startActionMode(it)
        }

        // Activity 启动 Floating Action
        floating_action_mode_activity_button.setOnClickListener {
    
    
            floatingActionModeController.startActionMode(requireActivity())
        }

        // View 启动 Floating Action
        floating_action_mode_view_button.setOnClickListener {
    
    
            floatingActionModeController.startActionMode(it)
        }
    }
}

Insert picture description here


More Kotlin-style packaging


ActionModeController is suitable for use in Java or Kotlin. If we only use it for Kotlin, we can build a more Kotlin style based on ActionModeController:

fun Activity.startActionMode(@MenuRes resId: Int, type: Int, onAction: (MenuItem) -> Unit) =
    ActionModeController(resId, type, onAction).startActionMode(this)

Through the extension function, ActionModeControllerthe definition and call are completely hidden , which is very concise.

Guess you like

Origin blog.csdn.net/vitaviva/article/details/108936869