onPrepareActionMode không được gọi khi tạo ActionMode


79

Tôi vừa hoàn thành việc điều chỉnh một trong các ứng dụng của mình sang thư viện ứng dụng và hỗ trợ v22.1.1 mới, hãy xem tại đâytại đây để biết thêm chi tiết. Khi tôi thực hiện một số thử nghiệm, có điều gì đó đã xảy ra với các ActionModes tôi đang sử dụng.

Khi bạn bắt đầu một ActionMode sử dụng một startSupportActionMode()cuộc gọi - nó không quan trọng nếu bạn sử dụng bây giờ bị phản ActionBarActivity lớp cơ sở hoặc mới AppCompatActivity lớp cơ sở - onPrepareActionMode()không được gọi.

Trong các phiên bản trước, bao gồm v21.0.3 & v22.0.0, onPrepareActionMode()được gọi tự động khi ActionMode được tạo ban đầu bằng cách sử dụng startSupportActionMode().

Tôi đã thử nghiệm nó trên thiết bị 2.2, 4.4.2 và 5.0, vì vậy nó có vẻ như không phụ thuộc vào phiên bản.

Có ai biết, nếu đây là hành vi dự định, đã được giới thiệu trong v22.1.1, hoặc một lỗi?

Tôi đã tìm thấy vấn đề này , nhưng không có nhiều phản hồi ở đây ...

Chỉnh sửa ngày 11 tháng 5 năm 2015:

Như đã đề cập trong trình theo dõi sự cố Android 159527 , sự cố này không chỉ ảnh hưởng đến v22.1.x của appcompat và thư viện hỗ trợ mà còn ảnh hưởng đến việc triển khai Android 5.1.

Hai giải pháp tạm thời khả thi vào lúc này, một giải pháp chung:

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

và một cái 'nhanh và bẩn' (khi bạn khởi tạo ActionMode của mình):

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

Nếu bạn không sử dụng appcompat ( ActionBarActivity/ AppCompatActivity), bạn cần thay thế startSupportActionMode()bằng startActionMode().

Thật không may, vẫn chưa rõ đây là hành vi dự định mới hay là một lỗi. Theo tài liệu API, đó là một lỗi / hồi quy, nhưng ai biết được ...


Tôi đồng ý với bạn - đây là một lỗi. Tôi chỉ chạy vào nó và dành một thời gian gỡ lỗi chỉ để phát hiện ra rằng onPrepare ... không được gọi nữa. Trong trường hợp của tôi, tôi nghĩ rằng nó sẽ làm việc chỉ đơn giản là cổng tất cả onPrepare tôi ... mã để onCreate ...
Peri Hartman

10
@darksaga: bạn nên chuyển bản chỉnh sửa của mình thành một câu trả lời và chấp nhận nó :)
Vicky Chijwani

Câu trả lời:


1

Tôi đã tạo một bản demo và nó hoạt động tốt, onPrepareActionMode được gọi mỗi khi chế độ hành động được hiển thị. Luôn được gọi sau onCreateActionMode, nhưng có thể được gọi nhiều lần nếu chế độ bị vô hiệu. [ Tôi yêu cầu bất kỳ ai thực hiện một chỉnh sửa nhỏ. Tôi cần màu thanh trạng thái giống như màu của thanh công cụ nhưng động, bạn có thể thấy Bố cục Drawyer không cần thiết được sử dụng để đạt được hiệu ứng này, Nhưng nếu tôi loại bỏ bố cục drawyer, màu thanh trạng thái sẽ không thay đổi theo màu thanh công cụ. Trong tiện ích, bạn có thể thấy theo mặc định màu chủ đề mặc định là màu đỏ, thanh công cụ thực sự có màu đỏ nhưng thanh trạng thái thì không, chỉ và chỉ khi tôi loại bỏ bố cục cửa sổ. Tôi cần làm điều này bằng cách sử dụng phong cách. ] Tạo bố cục tài nguyên và đặt tên cho nó => 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>

Tạo tên Hoạt động là 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;
    }
}

// Lớp Utils có phương thức thay đổi chủ đề // tôi đã tạo nó vì cần thay đổi chủ đề ứng dụng tự động nhập 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

Tôi đã có một vấn đề tương tự.

Sau khi tôi tăng giá trị của "compileSdkVersion" và "buildToolsVersion" của build.gradle, tôi phát hiện ra rằng onPrepareActionMode không được gọi.

  • compileSdkVersion: 21 đến 26
  • buildToolsVersion: 21.1.2 đến 26.0.2

Vì vậy, tôi đã chuyển mã của mình từ (A) sang (B). (vui lòng xem bên dưới)

Tôi không chắc đó có phải là giải pháp phù hợp hay không, nhưng nó hoạt động.

Đây là đoạn trích mã của tôi.

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;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.