75

我剛剛完成將我的一個應用程序調整到新的v22.1.1支持& appcompat庫,請參閱herehere以獲取更多詳細信息。當我做了一些測試時,我用的是ActionModesonPrepareActionMode創建ActionMode時未調用

當您啓動ActionMode使用startSupportActionMode()呼叫 - onPrepareActionMode()不會被調用 - 如果你用現在已經過時ActionBarActivity基類或新AppCompatActivity基類也沒關係。

在以前的版本中,包括v21.0.3 & v22.0.0,onPrepareActionMode()被自動調用,當ActionMode最初是使用startSupportActionMode()創建的。

我在2.2,4.0.2和5.0的設備上測試過它,所以它似乎不是版本相關的。

有誰知道,如果這是意向性行爲,那是在v22.1.1中引入的,或者是一個錯誤?

我發現這個issue,但有沒有很多在這裏的反饋...

編輯2015年5月11日:

正如Android issue tracker 159527提到的,這個問題不僅影響v22.1 .x的appcompat和支持庫,還有5.1的Android實現。此刻

兩個可能的臨時解決方案,一般的一個:

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

如果你不」 t使用appcompat(ActionBarActivity/AppCompatActivity)您需要將startSupportActionMode()替換爲startActionMode()

不幸的是,目前還不清楚這是否意味着新的行爲或錯誤。根據API doc這是一個錯誤/迴歸,但誰知道...

+0

我同意你的看法 - 這是一個錯誤。我只是碰到了它,並花了一些時間只有調試發現,onPrepare ......不叫了。在我的情況下,我認爲它會將所有onPrepare ...代碼移植到onCreate ... –

+9

@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」和的build.gradle的「buildToolsVersion」的值之後,我發現onPrepareActionMode不叫。

  • compileSdkVersion:21〜26
  • buildToolsVersion:21.1.2至26.0.2

所以我搬離(A)我的代碼(B)。 (請參見下文)

我不知道這是否是正確的解決方案,但它的工作原理。

這裏是我的代碼的摘錄。

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