話說程序猿都是段子手,看到有的程序猿寫文章,前面都會先寫一個段子,我這么有幽默感的段子手,也決定效仿一下。
“段子。”
寫完段子,下面開始進入正題。

今天要說的 ActionMode 是 Android 提供的一種實現菜單方式。Android 實現菜單的方式有很多種,比如 ActionBar、ToolBar、ContextMenu、OptionMenu、PopupMenu、PopupWindow 等等。ActionMode 自己之前一直沒用過,最近接手一個系統 app,里面有用這個,學習了下它的實現方式。ActionMode 是臨時占據了ActionBar的位置,使用起來也很簡單。先看下效果圖:

程序一運行,有一個 TextView 顯示 Hello World! ,為了作對比,我給出了一個 OptionMenu, 點擊 菜單選項,彈出相應的 Toast 。 點擊 Hello World,進入 ActionMode 模式,可以看到, ActionMode 臨時占用了 ActionBar , 點擊相應的 菜單選項,這里我也只是彈出相應的 Toast 以作演示。
下面貼出代碼,布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.joy.actionmodetest.MainActivity"> <TextView android:id="@+id/tv_test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </RelativeLayout>
在 res/menu 下面新建 OptionMenu 的布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/op_test1" android:icon="@mipmap/ic_launcher" android:title="menu1" app:showAsAction="always"/> <item android:id="@+id/op_test2" android:icon="@mipmap/ic_launcher" android:title="menu2" app:showAsAction="always"/> </menu>
同時還要在 res/menu 下面 新建一個xml 文件,作為 ActionMode 菜單的布局文件,如下:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/am_test1" android:icon="@mipmap/remind" android:title="menu1" app:showAsAction="always"/> <item android:id="@+id/am_test2" android:icon="@mipmap/favorites" android:title="menu2" app:showAsAction="always"/> </menu>
java 代碼如下:
package com.example.joy.actionmodetest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.ActionMode; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private TextView tv_test; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_test = (TextView) findViewById(R.id.tv_test); tv_test.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActionMode(new MyCallback()); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.option_menu,menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case R.id.op_test1: Toast.makeText(MainActivity.this,"option-menu1-test",Toast.LENGTH_SHORT).show(); break; case R.id.op_test2: Toast.makeText(MainActivity.this,"option-menu2-test",Toast.LENGTH_SHORT).show(); break; default: break; } return true; } private class MyCallback implements ActionMode.Callback { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.getMenuInflater().inflate(R.menu.action_mode_menu, menu); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.am_test1: Toast.makeText(MainActivity.this,"warning!",Toast.LENGTH_SHORT).show(); break; case R.id.am_test2: Toast.makeText(MainActivity.this,"favourite!",Toast.LENGTH_SHORT).show(); break; default: break; } mode.finish(); return true; } @Override public void onDestroyActionMode(ActionMode mode) { } } }
ActionMode 的使用非常簡單,調用 Activity 的 startActionMode 方法進入 ActionMode 模式即可,在不需要使用的時候調用 ActionMode 的 finish 方法退出 ActionMode 模式。startActionMode 方法接收一個 ActionMode.Callback 的參數,使用 ActionMode 的關鍵在於實現這個接口中 ActionMode 在各個聲明周期的回調方法:
onCreateActionMode(ActionMode, Menu) 在初始創建的時候調用
onPrepareActionMode(ActionMode, Menu) 在創建之后准備繪制的時候調用
onActionItemClicked(ActionMode, Menu) 當點擊 ActionMode 菜單選項的時候調用
onDestroyActionMode(ActionMode) 當退出 ActionMode 的時候調用
ActionMode 的 getMenuInflater 方法返回一個 MenuInflater 對象,用來加載 ActionMode 的菜單布局文件。現在這個 ActionMode 黑色背景,還帶點紅色底線,樣式很丑,自己都快看不下去了。那么怎么設置 ActionMode 的樣式呢?答案是通過 style 來設置。打開 res/values/styles.xml 文件進行修改。具體可以修改如下選項,每個選項的意義通過 name 屬性也都很清楚的體現出來:
<item name="actionModeStyle">@style/Widget.AppCompat.ActionMode</item> <item name="actionModeBackground">@drawable/abc_cab_background_top_material</item> <item name="actionModeSplitBackground">?attr/colorPrimaryDark</item> <item name="actionModeCloseDrawable">@drawable/abc_ic_ab_back_mtrl_am_alpha</item> <item name="actionModeCloseButtonStyle">@style/Widget.AppCompat.ActionButton.CloseMode</item> <item name="actionModeCutDrawable">@drawable/abc_ic_menu_cut_mtrl_alpha</item> <item name="actionModeCopyDrawable">@drawable/abc_ic_menu_copy_mtrl_am_alpha</item> <item name="actionModePasteDrawable">@drawable/abc_ic_menu_paste_mtrl_am_alpha</item> <item name="actionModeSelectAllDrawable">@drawable/abc_ic_menu_selectall_mtrl_alpha</item> <item name="actionModeShareDrawable">@drawable/abc_ic_menu_share_mtrl_alpha</item>
好了。ActionMode 就記這么一點,不能更多了...
