Как заставить использование переполнения меню на устройствах с помощью кнопки меню - PullRequest
158 голосов
/ 15 февраля 2012

Я бы хотел, чтобы все пункты меню, которые не вписывались в панель действий, переходили в меню переполнения (тот, который вызывается из панели действий, а не кнопка меню) даже на устройствах, которые do имеет кнопку меню .Это кажется гораздо более интуитивно понятным для пользователей, чем выбрасывание их в отдельный список меню, требующий от пользователя перехода от сенсорного (экранного) взаимодействия к взаимодействию на основе кнопок просто потому, что макет панели действий не помещается на панели.

В эмуляторе я могу установить значение «Аппаратная часть / Домашние ключи» на «нет» и получить этот эффект.Я искал способ сделать это в коде для фактического устройства, которое имеет кнопку меню, но не может точно.Кто-нибудь может мне помочь?

Ответы [ 11 ]

323 голосов
/ 11 июля 2012

Вы также можете использовать этот небольшой взлом здесь:

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 -Метод вашего класса приложения.

Это заставит приложениепоказать меню переполнения.Кнопка меню по-прежнему будет работать, но она откроет меню в верхнем правом углу.

[Редактировать] Так как он появлялся уже несколько раз: этот хак работает только для родного ActionBar, представленного в Android 3.0,не ActionBarSherlock.Последний использует свою собственную внутреннюю логику, чтобы решить, показывать ли меню переполнения.Если вы используете ABS, все платформы <4.0 обрабатываются ABS и, следовательно, подчиняются его логике.Хак все равно будет работать на всех устройствах с Android 4.0 или выше (вы можете смело игнорировать Android 3.x, поскольку на самом деле не существует планшетов с кнопкой меню). </p>

Существует специальный ForceOverflow-Тема, которая заставит меню в ABS, но, по всей видимости, в будущих версиях оно будет из-за сложностей .

54 голосов
/ 15 февраля 2012

РЕДАКТИРОВАТЬ: Изменено, чтобы ответить на ситуацию физической кнопки меню.

Это фактически предотвращено дизайном.В соответствии с разделом о совместимости Руководства по проектированию Android ,

"... переполнение действий доступно с помощью аппаратной клавиши меню. Полученное всплывающее окно действий ... отображается внизуэкрана. "

Вы заметите на скриншотах, что телефоны с физической кнопкой меню не имеют меню переполнения на панели действий.Это позволяет избежать двусмысленности для пользователя, по существу имея две кнопки для открытия одного и того же меню.

Для решения проблемы согласованности между устройствами: в конечном счете, для пользователя более важно, чтобы ваше приложение работало согласованно с любым другимприложение на том же устройстве, чем то, что оно ведет себя согласованно с собой на всех устройствах.

35 голосов
/ 30 августа 2013

Я использую, чтобы обойти это, определив свое меню следующим образом (также с иконкой 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);
}

: -)

11 голосов
/ 26 декабря 2013

Если вы используете панель действий из библиотеки поддержки (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>
7 голосов
/ 10 января 2013

Этот тип методов запрещен системой разработки для разработчиков Android, но я нашел способ его пройти:

Добавьте это в ваш 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;
    }
}
5 голосов
/ 09 марта 2012

Ну, я думаю, что Александр Лукас дал (к сожалению) правильный ответ, поэтому я отмечаю его как «правильный».Альтернативный ответ, который я добавляю здесь, состоит в том, чтобы просто указать новым читателям на этот пост в блоге разработчиков Android как довольно полное обсуждение темы с некоторыми конкретными предложениями о том, как обращаться с вашим кодом, когдапереход от предварительного уровня 11 к новой панели действий.

Я все еще считаю, что это была ошибка дизайна, когда кнопка меню не функционировала как избыточная кнопка «Переполнение действия» в устройствах с включенной кнопкой меню, как лучший способВ этот момент пользовательский опыт переходит, но его вода находится под мостом.

4 голосов
/ 09 июля 2012

Я не уверен, что это то, что вы ищете, но я построил подменю в меню ActionBar и установил его значок в соответствии со значком меню переполнения. Хотя на него не будут автоматически отправляться элементы (т. Е. Вы должны выбирать, что всегда видно и что всегда переполняется), мне кажется, что этот подход может вам помочь.

2 голосов
/ 12 ноября 2014

Если вы используете Панель инструментов , вы можете показать переполнение на всех версиях и на всех устройствах, я пробовал на некоторых устройствах 2.x, это работает.

2 голосов
/ 26 мая 2012

В приложении gmail, которое поставляется с предустановленной ICS, кнопка меню отключается, если выбрано несколько элементов.Меню переполнения здесь «принудительно» вызывается с помощью кнопки переполнения вместо кнопки физического меню.Существует сторонняя библиотека под названием ActionBarSherlock, которая позволяет вам «форсировать» меню переполнения.Но это будет работать только на уровне API 14 или ниже (до ICS)

1 голос
/ 31 августа 2015

Извините, если эта проблема не работает.

Вот что я сделал, чтобы устранить ошибку.Я пошел к макетам и создал две, содержащие панели инструментов.Один из них был макетом для SDK версии 8, а другой - для SDK версии 21. В версии 8 я использовал android.support.v7.widget.Toolbar, в то время как я использовал android.widget.Toolbar в макете SDK 21.

Затем я надуваю панель инструментов в своей деятельности.Я проверяю SDK, чтобы увидеть, был ли он 21 или выше.Затем я раздуваю соответствующий макет.Это заставит аппаратную кнопку отобразиться на панели инструментов, которую вы на самом деле создали.

...