创buildActionMode时不会调用onPrepareActionMode

我刚刚完成了一个我的应用程序调整到新的v22.1.1支持&appcompat库,看到这里和这里的更多细节。 当我做了一些testing的时候,我正在使用ActionModes 。

使用startSupportActionMode()调用启动ActionMode时 – 使用现在不推荐使用的ActionBarActivity基类或新的AppCompatActivity基类时onPrepareActionMode()onPrepareActionMode()没有被调用。

在以前的版本中,包括v21.0.3和v22.0.0,当ActionMode最初使用startSupportActionMode()创build时,会自动调用startSupportActionMode()

我在2.2,4.0.2和5.0版本的设备上testing过,所以它不是版本依赖的。

有没有人知道,如果这是意向的行为,这是在v22.1.1引入,或一个错误?

我发现这个问题 ,但是这里没有太多的反馈

2015年5月11日编辑:

正如Android问题追踪器159527中提到的,这个问题不仅影响到appcompat的v22.1.x和支持库,还影响到了5.1 Android的实现。

目前有两种可能的临时解决scheme,

 @Override public ActionMode startSupportActionMode(final ActionMode.Callback callback) { // Fix for bug https://code.google.com/p/android/issues/detail?id=159527 final ActionMode mode = super.startSupportActionMode(callback); if (mode != null) { mode.invalidate(); } return mode; } 

和一个“快速和肮脏的”(当你实例化你的ActionMode):

 final ActionMode actionMode = startSupportActionMode(new MyActionMode()); if(actionMode != null) { actionMode.invalidate(); } 

如果您不使用appcompat( ActionBarActivity / AppCompatActivity ),则需要用startActionMode()replacestartSupportActionMode() startActionMode()

不幸的是,目前还不清楚这是否意味着新的行为或错误。 根据API文档,这是一个错误/回归,但谁知道…

我已经创build了一个演示,它的工作正常,onPrepareActionMode每次显示动作模式时被调用。 总是在onCreateActionMode之后调用,但是如果模式无效,可能会被多次调用。 [ 我请求任何人做一个小编辑。 我需要状态栏颜色相同的工具栏,但dynamic,你可以看到不必要的canvas布局是用来实现这一效果,但如果我删除canvas布局状态栏颜色不会根据工具栏颜色更改。 在实用程序中,默认情况下可以看到默认的主题颜色是红色的,工具栏本质上是红色的,但是状态栏没有,只有当我删除了canvas布局时。 我需要使用风格来做到这一点。 ]创build资源布局并将其命名为=> action_mode_activity

 <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/my_drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical" app:insetForeground="#4000"> <include android:id="@+id/toolbar" layout="@layout/toolbar" /> <EditText android:id="@+id/editTextCopy" android:layout_width="fill_parent" android:layout_height="40dp" android:layout_marginTop="19dp" android:ems="10" android:inputType="textMultiLine" android:text="Long click to share!"> <requestFocus /> </EditText> </LinearLayout> </android.support.v4.widget.DrawerLayout> 

创build一个活动名称ActionModeActivity

 import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.ActionMode; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.Toast; import com.example.deepakpawar.demolearning.R; import com.example.deepakpawar.demolearning.demo.load.recycler.Utils; /** * Created by Deepak Pawar on 9/24/2015. */ public class ActionModeActivity extends AppCompatActivity implements View.OnLongClickListener, ActionMode.Callback { EditText editTextCopy; android.view.ActionMode mActionMode; private Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Utils.onActivityCreateSetTheme(this); setContentView(R.layout.action_mode_activity); // 1. Get the editText editTextCopy = (EditText) findViewById(R.id.editTextCopy); // 2. add long-click listener editTextCopy.setOnLongClickListener(this); toolbar = (Toolbar) findViewById(R.id.toolbar); if (toolbar != null) { setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true); actionBar.setTitle("Android Students"); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } } @Override public boolean onLongClick(View view) { // if actionmode is null "not started" if (mActionMode != null) { return false; } // Start the CAB mActionMode = this.startActionMode(this); view.setSelected(true); return true; } // 4. Called when the action mode is created; startActionMode() was called @Override public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.action_menu, menu); return true; } // 5. Called when the user click share item @Override public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.action_share: Toast.makeText(this, "Shared!", Toast.LENGTH_SHORT).show(); mode.finish(); // Action picked, so close the CAB return true; default: return false; } } // 6. Called each time the action mode is shown. Always called after onCreateActionMode, but // may be called multiple times if the mode is invalidated. @Override public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) { Toast.makeText(ActionModeActivity.this,"onPrepareActionMode Called ",Toast.LENGTH_SHORT).show(); return false; // Return false if nothing is done } // 7. Called when the user exits the action mode @Override public void onDestroyActionMode(android.view.ActionMode mode) { mActionMode = null; } } 

// Utils类有方法来改变主题//我创build它,因为需要dynamic地改变应用程序主题import android.app.Activity;

 public class Utils { private static int sTheme; public final static int THEME_DEFAULT = 0; public final static int THEME_WHITE = 1; public final static int THEME_BLUE = 2; /** * Set the theme of the Activity, and restart it by creating a new Activity of the same type. */ public static int getsTheme() { return sTheme; } public static void changeToTheme(Activity activity, int theme) { sTheme = theme; activity.recreate(); // activity.finish(); // activity.startActivity(new Intent(activity, activity.getClass())); } /** * Set the theme of the activity, according to the configuration. */ public static void onActivityCreateSetTheme(Activity activity) { switch (sTheme) { default: case THEME_DEFAULT: activity.setTheme(R.style.FirstTheme); break; case THEME_WHITE: activity.setTheme(R.style.SecondTheme); break; case THEME_BLUE: activity.setTheme(R.style.Thirdheme); break; } } } 

V21-的themes.xml

 <resources> <style name="AppTheme" parent="AppTheme.Base"> <item name="android:windowContentTransitions">true</item> <item name="android:windowAllowEnterTransitionOverlap">true</item> <item name="android:windowAllowReturnTransitionOverlap">true</item> <item name="android:windowSharedElementEnterTransition">@android:transition/move</item> <item name="android:windowSharedElementExitTransition">@android:transition/move</item> <item name="android:actionOverflowButtonStyle">@style/Widget.ActionButton.Overflow</item> <!-- <item name="android:navigationBarColor">@color/PrimaryColor</item>--> <item name="windowActionBar">false</item> <item name="windowActionModeOverlay">true</item> <!-- To Make Navigation Drawer Fill Status Bar and become Transparent Too --> <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@android:color/transparent</item> <!--//if darker status bar needed--> <!-- <item name="android:windowTranslucentStatus">true</item>--> </style> <style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/PrimaryColor</item> <item name="colorPrimaryDark">@color/PrimaryDarkColor</item> <item name="colorAccent">@color/AccentColor</item> <item name="android:textColorPrimary">@color/TextPrimaryColor</item> <item name="android:windowBackground">@color/WindowBackground</item> </style> <style name="Widget.ActionButton.Overflow" parent="@android:style/Widget.Holo.ActionButton.Overflow"> <item name="android:contentDescription">@string/accessibility_overflow</item> </style> <!-- style for the tool bar backgrounds --> <style name="ToolBarStyle" parent="ToolBarStyle.Base" /> <style name="ToolBarStyle.Base" parent=""> <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item> <item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item> </style> <style name="ToolBarStyle.Event" parent="ToolBarStyle"> <item name="titleTextAppearance">@style/TextAppearance.Widget.Event.Toolbar.Title</item> </style> <style name="TextAppearance.Widget.Event.Toolbar.Title" parent="TextAppearance.Widget.AppCompat.Toolbar.Title"> <!--Any text styling can be done here--> <item name="android:textStyle">normal</item> <item name="android:textSize">18sp</item> <item name="android:textColor">#000000</item> </style> <!-- Customize your theme example here. --> <style name="FirstTheme"> <item name="android:textColor">#FF0000</item> <item name="colorPrimary">#FF0000</item> <item name="colorPrimaryDark">#ff0000</item> <item name="colorAccent">#ff0087</item> <item name="android:shadowColor">#00ccff</item> <item name="android:shadowRadius">1.5</item> <item name="android:shadowDy">1</item> </style> <style name="SecondTheme"> <item name="android:textColor">#00FF00</item> <item name="colorPrimary">#00FF00</item> <item name="colorPrimaryDark">#00FF00</item> <item name="colorAccent">#00FF90</item> <item name="android:shadowColor">#00ccff</item> <item name="android:shadowRadius">1.5</item> <item name="android:shadowDy">1</item> </style> <style name="Thirdheme"> <item name="android:textColor">#0000F0</item> <item name="colorPrimary">#0000F0</item> <item name="colorPrimaryDark">#0000F0</item> <item name="colorAccent">#0090F0</item> <item name="android:shadowColor">#00ccff</item> <item name="android:shadowRadius">1.5</item> <item name="android:shadowDy">1</item> </style> <style name="AppCompatAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert"> <item name="colorAccent">#FFCC00</item> <item name="android:textColorPrimary">#FFFFFF</item> <item name="android:background">#5fa3d0</item> </style> </resources> 

我有一个类似的问题。

当我提高了build.gradle的“compileSdkVersion”和“buildToolsVersion”的值后,我发现onPrepareActionMode没有被调用。

  • compileSdkVersion:21到26
  • buildToolsVersion:21.1.2到26.0.2

所以我把代码从(A)移到(B)。 (请看下面)

我不知道这是否是正确的解决scheme,但它的工作原理。

这是我的代码的摘录。

 list1 = findViewById(R.id.listView1); list1.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { //(A) //MenuItem menuItem1 = menu.findItem(R.id.menu_item1); //menuItem1.setVisible(false); return false; } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_action_mode, menu); //(B) MenuItem menuItem1 = menu.findItem(R.id.menu_item1); menuItem1.setVisible(false); return true; }