创建 ActionMode 时不调用 onPrepareActionMode

我刚刚调整了我的一个应用程序到新的 v22.1.1支持和应用程序库,请参阅 给你给你了解更多细节。当我做一些测试时,我使用的 行动模式有些不对劲。

当您使用 startSupportActionMode()调用启动 动作模式时-无论您使用现在已废弃的 活动基类还是新的 AppCompatActivity基类-onPrepareActionMode()没有被调用。

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

我在2.2、4.4.2和5.0设备上测试了它,所以它似乎不依赖于版本。

有没有人知道,如果这是在 v22.1.1中引入的预期行为,还是一个 bug?

我找到了这个 问题,但这里没有太多的反馈..。

2015年5月11日编辑:

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

目前有两个可能的临时解决方案,一个普遍的解决方案:

@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()代替 startSupportActionMode()

不幸的是,目前还不清楚这是有意的新行为还是 bug。根据 空气污染指数文件的数据,这是一个错误/回归,但谁知道呢..。

5274 次浏览

我已经创建了一个演示,它的工作很好,onPrepareActionMode 在每次显示操作模式时都会被调用。总是在 onCreateActionMode 之后调用,但是 如果该模式无效,则可以多次调用。 [ 我要求任何人做一个小小的修改。 我需要状态栏的颜色相同的工具栏,但动态, 您可以看到不必要的抽屉布局是用来实现这一效果,但如果我删除抽屉布局的状态栏颜色不改变根据工具栏颜色。 在实用程序中,你可以看到默认的主题颜色是红色,工具栏最初得到红色,但状态栏没有,只有当我删除抽屉布局。 我需要用自己的风格来做这件事。 ] 创建一个资源布局并将其命名为: 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>

创建一个名为 itActionModeActivity 的活动

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;
}
}

//使用具有更改主题的方法的类 //i 创建它是因为需要动态更改应用程序主题 活动;

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-主题. 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 的“ buildSdkVersion”和“ buildToolsVersion”的值之后,我发现 onPrepareActionMode 没有被调用。

  • 二十一到二十六个版本
  • BuildToolsVersion: 21.1.2 to 26.0.2 buildToolsVersion: 21.1.2 to 26.0.2

所以我把我的代码从(A)移到(B)

我不确定这是否是正确的解决方案,但它确实有效。

下面是我的代码的摘录。

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;
}