Как принудительно использовать меню переполнения на устройствах с помощью кнопки меню
Я бы хотел, чтобы все элементы меню, которые не вписываются в ActionBar, переходят в меню переполнения (тот, который достигается из панели действий, а не кнопки меню) даже на устройствах, которые делают есть кнопка меню. Это кажется гораздо более понятным для пользователей, чем бросание их в отдельный список меню, который требует от пользователя перехода от сенсорного (экранного) взаимодействия к взаимодействию на основе кнопок просто потому, что макет ActionBar не может поместиться на панели.
В эмуляторе я могу установить значение "Оборудование назад/Домашние ключи" на "нет" и получить этот эффект.
Я искал способ сделать это в коде для фактического устройства, которое имеет кнопку меню, но не может его отличить. Кто-нибудь может мне помочь?
Ответы
Ответ 1
EDIT: изменено для ответа на ситуацию с физической кнопкой меню.
Это фактически предотвращается дизайном. Согласно разделу совместимости Руководства по дизайну Android,
"... переполнение действия доступно с помощью аппаратного ключа меню. Результатные всплывающие окна отображаются в нижней части экрана.
На снимках экрана вы заметите, что телефоны с физической кнопкой меню не имеют меню переполнения в ActionBar. Это позволяет избежать двусмысленности для пользователя, по существу имеющего две кнопки для открытия того же самого меню.
Чтобы решить проблему согласованности между устройствами: в конечном счете, более важно, чтобы ваше приложение работало последовательно с каждым другим приложением на том же самом устройстве, а не тем, что оно ведет себя с собой на всех устройствах.
Ответ 2
Вы также можете использовать этот маленький хак здесь:
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception ignored) {
}
Хорошим местом для этого было бы onCreate
-Method вашего класса Application.
Это заставит приложение отображать меню переполнения. Кнопка меню по-прежнему будет работать, но она откроет меню в верхнем правом углу.
[Edit] Так как он появился несколько раз: этот хак работает только для родного ActionBar, представленного в Android 3.0, а не ActionBarSherlock. Последний использует свою собственную внутреннюю логику, чтобы решить, показывать ли это меню переполнения. Если вы используете ABS, все платформы < 4.0 обрабатываются АБС и, таким образом, подвергаются его логике. Хак по-прежнему будет работать на всех устройствах с Android 4.0 или выше (вы можете спокойно игнорировать Android 3.x, поскольку на нем нет никаких таблеток с кнопкой меню).
Существует специальная ForceOverflow-тема, которая заставит меню в АБС, но, возможно, будет удалено в будущих версиях из-за осложнений.
Ответ 3
Я использую, чтобы обойти это, определяя мое меню, подобное этому (также с помощью значка ActionBarSherlock, используемого в моем примере):
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_overflow"
android:icon="@drawable/abs__ic_menu_moreoverflow_normal_holo_light"
android:orderInCategory="11111"
android:showAsAction="always">
<menu>
<item
android:id="@+id/menu_overflow_item1"
android:showAsAction="never"
android:title="@string/overflow_item1_title"/>
<item
android:id="@+id/menu_overflow_item2"
android:showAsAction="never"
android:title="@string/overflow_item2_title"/>
</menu>
</item>
</menu>
Я признаю, что это может потребовать ручного управления переполнением в вашем xml, но я нашел это решение полезным.
Вы также можете заставить устройство использовать кнопку HW для открытия меню переполнения в вашей деятельности:
private Menu mainMenu;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO: init menu here...
// then:
mainMenu=menu;
return true;
}
@Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
if (mainMenu !=null) {
mainMenu.performIdentifierAction(R.id.menu_overflow, 0);
}
}
return super.onKeyUp(keycode, e);
}
: -)
Ответ 4
Если вы используете панель действий из библиотеки поддержки (android.support.v7.app.ActionBar
), используйте следующее:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yorapp="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/menu_overflow"
android:icon="@drawable/icon"
yourapp:showAsAction="always"
android:title="">
<menu>
<item
android:id="@+id/item1"
android:title="item1"/>
<item
android:id="@+id/item2"
android:title="item2"/>
</menu>
</item>
</menu>
Ответ 5
Этот метод запрещен системой разработки Android Developers, но я нашел способ передать ее:
Добавьте это в свой файл меню XML:
<item android:id="@+id/pick_action_provider"
android:showAsAction="always"
android:title="More"
android:icon="@drawable/ic_action_overflow"
android:actionProviderClass="com.example.AppPickActionProvider" />
Затем создайте класс с именем "AppPickActionProvider" и скопируйте ему следующий код:
package com.example;
import android.content.Context;
import android.util.Log;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
public class AppPickActionProvider extends ActionProvider implements
OnMenuItemClickListener {
static final int LIST_LENGTH = 3;
Context mContext;
public AppPickActionProvider(Context context) {
super(context);
mContext = context;
}
@Override
public View onCreateActionView() {
Log.d(this.getClass().getSimpleName(), "onCreateActionView");
return null;
}
@Override
public boolean onPerformDefaultAction() {
Log.d(this.getClass().getSimpleName(), "onPerformDefaultAction");
return super.onPerformDefaultAction();
}
@Override
public boolean hasSubMenu() {
Log.d(this.getClass().getSimpleName(), "hasSubMenu");
return true;
}
@Override
public void onPrepareSubMenu(SubMenu subMenu) {
Log.d(this.getClass().getSimpleName(), "onPrepareSubMenu");
subMenu.clear();
subMenu.add(0, 1, 1, "Item1")
.setIcon(R.drawable.ic_action_home).setOnMenuItemClickListener(this);
subMenu.add(0, 2, 1, "Item2")
.setIcon(R.drawable.ic_action_downloads).setOnMenuItemClickListener(this);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch(item.getItemId())
{
case 1:
// What will happen when the user presses the first menu item ( 'Item1' )
break;
case 2:
// What will happen when the user presses the second menu item ( 'Item2' )
break;
}
return true;
}
}
Ответ 6
Ну, я думаю, что Александр Лукас предоставил (к сожалению) правильный ответ, поэтому я отмечаю его как "правильный". Альтернативный ответ, который я добавляю здесь, - это просто указать всех новых читателей на этот пост в блоге Android Developers как довольно полное обсуждение темы с некоторыми конкретными предложениями, как как обращаться с вашим кодом при переходе с предварительного уровня 11 на новую панель действий.
Я по-прежнему считаю, что ошибкой дизайна не было, если кнопка меню ведет себя как избыточная кнопка "Переполнение действия" на устройствах с включенной кнопкой меню, что является лучшим способом перехода на пользовательский интерфейс, но его вода под мостом на данный момент.
Ответ 7
Я не уверен, что это то, что вы ищете, но я создал подменю в меню ActionBar и установил его значок в соответствии с иконкой меню переполнения. Хотя он не будет автоматически отправляться на него, (IE вы должны выбрать то, что всегда видно и что всегда переполнено), мне кажется, что этот подход может вам помочь.
Ответ 8
В приложении gmail, которое поставляется с установленной программой ICS, кнопка меню отключена, когда у вас есть несколько элементов. Меню переполнения здесь "принудительно" запускается с помощью кнопки переполнения вместо кнопки физического меню. Theres - сторонняя библиотека под названием ActionBarSherlock, которая позволяет "принудительно" переполнять меню. Но это будет работать только на уровне API 14 или ниже (pre-ICS)
Ответ 9
Если вы используете Toolbar, вы можете показать переполнение всех версий и всех устройств, я пробовал на некоторых 2.x устройств, он работает.
Ответ 10
Извините, если эта проблема не работает.
Вот что я сделал для устранения ошибки. Я пошел в макеты и создал два, содержащих панели инструментов. Один из них был макет для SDK версии 8, а другой для sdk версии 21. В версии 8 я использовал android.support.v7.widget.Toolbar, в то время как я использовал android.widget.Toolbar на макете sdk 21.
Затем я раздуваю панель инструментов в своей деятельности. Я проверяю sdk, чтобы узнать, было ли это 21 или выше. Затем я раздуваю соответствующий макет. Это заставляет аппаратную кнопку отображать на панели инструментов, которую вы на самом деле разработали.
Ответ 11
Для тех, кто использует новый Toolbar
:
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
...
}
@Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
mToolbar.showOverflowMenu();
return true;
}
return super.onKeyUp(keycode, e);
}