onPrepareActionMode не викликається під час створення ActionMode


79

Я щойно закінчив налаштовувати один із своїх додатків на нову бібліотеку підтримки & vcomponent v22.1.1, див. Тут і тут, щоб дізнатися більше. Коли я провів тестування, щось не було в режимах ActionModes, якими я користуюся.

Коли ви запускаєте ActionMode за допомогою startSupportActionMode()виклику - не має значення, використовуєте ви вже застарілий базовий клас ActionBarActivity чи новий базовий клас AppCompatActivity - onPrepareActionMode()не викликається.

У попередніх версіях, включаючи v21.0.3 і v22.0.0, onPrepareActionMode()було викликано автоматично, коли ActionMode був спочатку створений за допомогою startSupportActionMode().

Я протестував його на пристроях 2.2, 4.4.2 та 5.0, тому, здається, це не залежить від версії.

Хтось знає, якщо це передбачувана поведінка, яка була введена у v22.1.1, або помилка?

Я знайшов цю проблему , але тут не так багато відгуків ...

Редагувати 11 травня 2015 року:

Як згадувалося в трекері випусків Android 159527 , це питання впливає не лише на v22.1.x appcompat та бібліотеку підтримки, але й на реалізацію Android 5.1.

На даний момент є два можливі тимчасові рішення, загальне:

@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 , це помилка / регресія, але хто знає ...


Я згоден з вами - це помилка. Я просто натрапив на нього і витратив деякий час на налагодження, лише виявивши, що onPrepare ... більше не викликається. У моєму випадку, я думаю, це буде працювати, щоб просто перенести весь мій код onPrepare ... на onCreate ...
Пері Хартман

10
@darksaga: вам слід перетворити свою редакцію на відповідь і прийняти її :)
Вікі Чійвані

Відповіді:


1

Я створив демонстраційну версію і працює нормально, onPrepareActionMode викликається кожного разу, коли відображається режим дії. Завжди викликається після onCreateActionMode, але може бути викликаний кілька разів, якщо режим скасовано. [ Я прошу когось зробити невелику редакцію. Мені потрібен колір рядка стану такий же, як і на панелі інструментів, але динамічно, ви бачите, що для досягнення цього ефекту використовується непотрібний макет Drawyer, але якщо я видалю макет Drayer, колір рядка стану не змінюється залежно від кольору панелі інструментів. У програмі ви можете бачити за замовчуванням колір теми за замовчуванням червоний, панель інструментів фактично отримує червоний колір, але рядок стану не робить, лише і лише якщо я видалю макет шухляди. Мені потрібно зробити це, використовуючи стиль. ] Створіть макет ресурсу та назвіть його => 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>

Створіть ім'я Діяльність - 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>

0

У мене була подібна проблема.

Після того, як я підвищив значення "compileSdkVersion" і "buildToolsVersion" build.gradle, я виявив, що onPrepareActionMode не викликався.

  • compileSdkVersion: з 21 по 26
  • buildToolsVersion: 21.1.2 - 26.0.2

Тож я переніс свій код з (А) в (В). (Дивіться нижче)

Я не впевнений, що це правильне рішення, але воно працює.

Ось витяг мого коду.

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;
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.