75

Właśnie zakończyłem dostosowywanie jednej z moich aplikacji do nowych bibliotek obsługi aplikacji v22.1.1 &, zobacz here i here, aby uzyskać więcej szczegółów. Kiedy zrobiłem kilka testów, coś było wyłączone z ActionModes używam.Tryb onPrepareActionMode nie był wywoływany podczas tworzenia ActionMode

Po uruchomieniu ActionMode użyciu startSupportActionMode() rozmowy - to nie ma znaczenia, jeśli używasz już nieaktualna ActionBarActivity klasę bazową lub nową klasę AppCompatActivity podstawa - onPrepareActionMode() nie jest wywoływana.

W poprzednich wersjach, w tym v21.0.3 & v22.0.0, onPrepareActionMode() został wywołany automatycznie, gdy tryb działania został początkowo utworzony przy użyciu startSupportActionMode().

Testowałem to na urządzeniach 2.2, 4.4.2 i 5.0, więc wygląda na to, że nie zależy to od wersji.

Czy ktoś wie, czy jest to zamierzone zachowanie, które zostało wprowadzone w wersji 22.1.1, czy błąd?

Znalazłem issue, ale nie ma zbyt dużo informacji zwrotnych tutaj ...

Edycja 11 maja 2015:

Jak wspomniano w Android issue tracker 159527, kwestia ta nie tylko wpływa na v22.1 .x aplikacji appcompat i biblioteki wsparcia, ale także implementacja systemu Android 5.1.

dwa możliwe rozwiązania tymczasowe w tej chwili, ogólny One:

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

i 'szybkie i brudne' jeden (jeśli instancję swoje ActionMode):

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

Jeśli don” t użyj appcompat (ActionBarActivity/AppCompatActivity) musisz zastąpić startSupportActionMode() przez startActionMode().

Niestety, wciąż nie jest jasne, czy jest to zamierzone nowe zachowanie, czy błąd. Według API doc jest to błąd/regresja, ale kto wie ...

+0

Zgadzam się z Państwem - to błąd. Po prostu wpadłem na to i spędziłem trochę czasu na debugowaniu, aby odkryć, że onPrepare ... nie jest już wywoływany. W moim przypadku, myślę, że będzie działać, aby po prostu przenieść cały mój kod onPrepare ... do onCreate ... –

+9

@darksaga: powinieneś przekonwertować swoją edycję na odpowiedź i ją zaakceptować :) –

Odpowiedz

1

Utworzyłem demo i działa poprawnie, onPrepareActionMode jest wywoływana za każdym razem, gdy wyświetlany jest tryb działania. Zawsze wywoływana po onCreateActionMode, ale może być wywołana wiele razy, jeśli tryb jest unieważniony. [ Żądam, aby ktoś zrobił małą zmianę. Potrzebuję koloru paska stanu takiego samego jak pasek narzędzi, ale dynamicznie, widać, że niepotrzebny układ Drawyer jest używany do osiągnięcia tego efektu, ale jeśli usunę ten układ, kolor paska stanu nie zmieni się zgodnie z kolorem paska narzędzi. W narzędziu domyślnie widoczny jest domyślny kolor motywu jest czerwony, pasek narzędzi dostaje czerwony kolor, ale pasek stanu nie, tylko i tylko wtedy, gdy usuniemy drawyer układ. Muszę to zrobić za pomocą stylu. ] utworzyć układ zasobów i nadaj mu nazwę => 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> 

Utwórz nazwę Activity to 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; 
    } 
} 

// klasa Utils mający sposób zmienić motyw // i stworzył go, ponieważ trzeba zmienić motyw aplikacji dynamicznie import 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

miałem podobny problem.

Po tym, jak podniosłem wartość "compileSdkVersion" i "buildToolsVersion" z build.gradle, dowiedziałem się, że onPrepareActionMode nie został wywołany.

  • compileSdkVersion: 21 do 26
  • buildToolsVersion: 21.1.2 do 26.0.2

Więc przeniosłem mój kod z (a) do (b). (zobacz poniżej)

Nie jestem pewien, czy to właściwe rozwiązanie, ale działa.

Oto fragment mojego kodu.

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; 
    } 
Powiązane problemy