Я только что закончил адаптировать одно из своих приложений к новым библиотекам поддержки и совместимости приложений v22.1.1, подробнее см. Здесь и здесь . Когда я провел некоторое тестирование, что-то было не так с режимами действий, которые я использую.
Когда вы запускаете ActionMode с помощью startSupportActionMode()
вызова - не имеет значения, используете ли вы устаревший базовый класс ActionBarActivity или новый базовый класс AppCompatActivity - onPrepareActionMode()
не вызывается.
В предыдущих версиях, включая v21.0.3 и v22.0.0, onPrepareActionMode()
вызывался автоматически, когда ActionMode изначально создавался с использованием startSupportActionMode()
.
Я тестировал его на устройствах 2.2, 4.4.2 и 5.0, поэтому, похоже, он не зависит от версии.
Кто-нибудь знает, если это предполагаемое поведение, которое было введено в v22.1.1, или ошибка?
Я обнаружил эту проблему , но здесь не так много отзывов ...
Изменить 11 мая 2015 г .:
Как упоминалось в системе отслеживания проблем Android 159527 , эта проблема затрагивает не только v22.1.x appcompat и библиотеки поддержки, но и реализацию Android 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()
.
К сожалению, до сих пор не ясно, является ли это новым поведением или ошибкой. Согласно документу API , это ошибка / регресс, но кто знает ...
Ответы:
Я создал демонстрацию, и она работает нормально, 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; } }
// Использует класс, у которого есть метод для изменения темы // Я создал его, потому что необходимо динамически изменять тему приложения 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>
источник
У меня была аналогичная проблема.
После того, как я увеличил значение compileSdkVersion и buildToolsVersion для build.gradle, я обнаружил, что onPrepareActionMode не вызывается.
Поэтому я переместил свой код из (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; }
источник