75

Ich habe gerade eine meiner Apps an die neue v22.1.1-Unterstützung & appcompat libraries angepasst, siehe here und here für weitere Details. Als ich etwas getestet habe, war etwas los mit der ActionModes, die ich benutze.onPrepareActionMode nicht aufgerufen beim Erstellen von ActionMode

Wenn Sie beginnen, ein ActionMode einen startSupportActionMode() Anruf mit - es ist nicht, ob Sie die jetzt veraltet ActionBarActivity Basisklasse oder die neue AppCompatActivity Basisklasse verwenden, egal - onPrepareActionMode() heißt nicht werden.

In früheren Versionen, einschließlich v21.0.3 & v22.0.0 wurde onPrepareActionMode() automatisch aufgerufen, wenn die ActionMode zunächst mit startSupportActionMode() erstellt wurde.

Ich habe es auf einem 2.2, 4.4.2 und 5.0 Gerät getestet, so dass es nicht versionsabhängig zu sein scheint.

Weiß jemand, ob das beabsichtigte Verhalten, das in v22.1.1 eingeführt wurde, oder ein Fehler ist?

fand ich diese issue, aber es gibt nicht viel Feedback hier ...

Bearbeiten 2015 11. Mai:

Wie in den Android issue tracker 159527 erwähnt, dieses Problem betrifft nicht nur die v22.1 .x von appcompat und der Support-Bibliothek, aber auch die 5.1 Android-Implementierung.

Zwei mögliche temporäre Lösungen im Moment, ein allgemeiner Art:

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

und ein 'quick and dirty' ein (wenn Sie instanziiert Ihre ActionMode):

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

Wenn Sie don‘ t verwenden Sie appcompat (ActionBarActivity/AppCompatActivity) müssen Sie startSupportActionMode() durch startActionMode() ersetzen.

Leider ist es immer noch nicht klar, ob dies ein neues Verhalten oder ein Fehler ist. Laut der API doc ist es ein Bug/Regression, aber wer weiß ...

+0

Ich stimme dir zu - das ist ein Fehler. Ich bin einfach hineingelaufen und habe etwas Zeit mit dem Debuggen verbracht, nur um festzustellen, dass onPrepare ... nicht mehr aufgerufen wird. In meinem Fall, ich denke, es wird funktionieren, um alle meine onPrepare ... Code zu onCreate ... –

+9

@darksaga Port: Sie sollten Ihre Bearbeitung in eine Antwort konvertieren und akzeptieren :) –

Antwort

1

Ich habe eine Demo erstellt und es funktioniert gut, onPrepareActionMode wird jedes Mal aufgerufen, wenn der Aktionsmodus angezeigt wird. Wird immer nach onCreateActionMode aufgerufen, aber kann mehrmals aufgerufen werden, wenn der Modus ungültig ist. [ Ich fordere jeden an, einen kleinen Schnitt zu machen. Ich brauche Statusleiste Farbe wie die der Symbolleiste aber dynamisch, Sie können sehen, unnötige Drawyer Layout wird verwendet, um diesen Effekt zu erzielen, aber wenn ich Drawyer Layout entfernen die Statusleiste Farbe ändert sich nicht entsprechend Symbolleiste Farbe. Im Dienstprogramm können Sie sehen, Standard-Thema Farbe ist rot, Symbolleiste anfängt rot, aber Statusleiste nicht, nur und nur, wenn ich Drawyer Layout entfernen. Ich muss dies mit Stil tun. ] erstellen Ressource Layout und nennen Sie es => 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> 

einen Aktivitätsname erstellen 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-Klasse mit Methode Thema ändern // Ich habe es wegen müssen App-Thema dynamisch ändern importieren 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

hatte ich ein ähnliches Problem.

Nachdem ich den Wert von "compileSdkVersion" und "buildToolsVersion" von build.gradle erhöht habe, fand ich heraus, dass onPrepareActionMode nicht aufgerufen wurde.

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

Also zog ich meinen Code von (A) zu (B). (siehe unten)

Ich bin mir nicht sicher, ob es die richtige Lösung ist, aber es funktioniert.

Hier ist der Auszug meines Codes.

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; 
    } 
Verwandte Themen