ActionMode बनाते समय onPrepareActionMode को नहीं बुलाया जाता है


79

मैंने अभी अपने एक ऐप को नए v22.1.1 सपोर्ट एंड ऐप्पोमैट लाइब्रेरी में एडजस्ट करने का काम पूरा किया है, अधिक जानकारी के लिए यहां और यहां देखें। जब मैंने कुछ परीक्षण किया, तो एक्शनमॉड्स के साथ कुछ बंद था जिसका मैं उपयोग कर रहा हूं।

जब आप एक कॉल का उपयोग करके एक्शनमोड शुरू करते startSupportActionMode()हैं - इससे कोई फर्क नहीं पड़ता कि आप अब अपग्रेड किए गए एक्शनबेरक्टिविटी बेस क्लास या नए AppCompatActivity बेस क्लास का उपयोग करते हैं - onPrepareActionMode()तो नहीं कहा जा रहा है।

पिछले संस्करणों में, v21.0.3 और v22.0.0 सहित, onPrepareActionMode()स्वचालित रूप से कॉल किया गया था, जब ActionMode का उपयोग शुरू में किया गया था startSupportActionMode()

मैंने इसे 2.2, 4.4.2 और 5.0 डिवाइस पर परीक्षण किया, इसलिए ऐसा लगता है कि यह संस्करण पर निर्भर नहीं है।

क्या किसी को पता है, अगर यह अभिप्रेत व्यवहार है, जिसे v22.1.1, या बग में पेश किया गया है?

मुझे यह मुद्दा मिला , लेकिन यहाँ बहुत प्रतिक्रिया नहीं है ...

11 मई 2015 को संपादित करें:

जैसा कि एंड्रॉइड इश्यू ट्रैकर 159527 में उल्लेख किया गया है , यह समस्या न केवल ऐप्पोमैट के v22.1.x और समर्थन पुस्तकालय को प्रभावित करती है, बल्कि 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()

दुर्भाग्य से यह अभी भी स्पष्ट नहीं है अगर यह नया व्यवहार या बग है। एपीआई डॉक्टर के अनुसार यह एक बग / प्रतिगमन है, लेकिन कौन जानता है ...


मैं आपसे सहमत हूँ - यह एक बग है। मैं बस इसमें भाग गया और कुछ समय डिबगिंग में केवल उस खोज को खोजने में बिताया ... जिसे कोई और नहीं कहा जाता है। मेरे मामले में, मुझे लगता है कि यह मेरे सभी ऑनपेयर को बस पोर्ट करने का काम करेगा ... कोड को ऑनक्रिएट करें ...
पेरी हार्टमैन

10
@darksaga: आपको अपने संपादन को एक उत्तर में बदलना चाहिए और इसे स्वीकार करना चाहिए :)
विक्की चिजवानी

जवाबों:


1

मैंने एक डेमो बनाया है और इसका ठीक काम है, 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>

एक गतिविधि नाम बनाएँ इसे 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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.