【问题标题】:onPrepareActionMode not called when creating ActionMode创建 ActionMode 时未调用 onPrepareActionMode
【发布时间】:2015-07-07 18:47:11
【问题描述】:

我刚刚将我的一个应用程序调整为新的 v22.1.1 支持和 appcompat 库,请参阅 herehere 了解更多详细信息。当我进行一些测试时,我正在使用的 ActionModes 出现问题。

当您使用 startSupportActionMode() 调用启动 ActionMode 时 - 使用现在已弃用的 ActionBarActivity 基类或新的 AppCompatActivity 基类并不重要 - 不会调用 onPrepareActionMode()

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

我在 2.2、4.4.2 和 5.0 设备上对其进行了测试,所以它似乎与版本无关。

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

我找到了这个issue,但是这里没有很多反馈...

2015 年 5 月 11 日编辑:

正如Android issue tracker 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),则需要将 startSupportActionMode() 替换为 startActionMode()

不幸的是,目前尚不清楚这是有意的新行为还是错误。根据API doc,这是一个错误/回归,但谁知道...

【问题讨论】:

  • 我同意你的看法 - 这是一个错误。我刚刚遇到它并花了一些时间调试才发现 onPrepare... 不再被调用。就我而言,我认为将我的所有 onPrepare... 代码简单地移植到 onCreate...
  • @darksaga:您应该将您的编辑转换为答案并接受它:)

标签: android android-support-library android-actionmode android-appcompat


【解决方案1】:

我也遇到过类似的问题。

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

  • compileSdkVersion : 21 到 26
  • buildToolsVersion : 21.1.2 到 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;
    }

【讨论】:

    【解决方案2】:

    我创建了一个演示,它工作正常,每次显示动作模式时都会调用 onPrepareActionMode。总是在 onCreateActionMode 之后调用,但是 如果模式无效,可能会被多次调用。 [ 我请求任何人进行小修改。 我需要与工具栏颜色相同但动态的状态栏颜色, 您可以看到不必要的 Drawyer 布局用于实现此效果,但是如果我删除 drawyer 布局,状态栏颜色不会根据工具栏颜色而改变。 在实用程序中,默认情况下您可以看到默认主题颜色为红色,工具栏最初变为红色,但状态栏不会,仅当我删除 drawyer 布局时。 我需要使用样式来做到这一点。 ] 创建资源布局并命名 => 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>
    

    创建一个Activity,命名为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类 // 我创建它是因为需要动态更改应用程序主题 导入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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多