Menü düğmeli cihazlarda taşma menüsünü kullanmaya zorlama


159

Ben taşma menüsüne İşlem Çubuğu halindeyken (Eylem Bar değil menü düğmesi ulaşılır biri) sığmayan tüm menü öğelerini almak istiyorum hatta cihazlarda yapmak bir Menü düğmesi . Bu, kullanıcıların ActionBar'ın düzeni çubuğa sığmadığından, kullanıcının dokunmatik (ekran) bir etkileşimden düğme tabanlı bir etkileşime atlamasını gerektiren ayrı bir menü listesine atmaktan çok daha sezgisel görünüyor.

Emülatörde "Donanım Geri / Giriş Tuşları" değerini "hayır" olarak ayarlayabilir ve bu efekti elde edebilirim. Bir menü düğmesi olan ama iyi olamaz gerçek bir cihaz için kod bunu yapmak için bir yol aradım. Biri bana yardım edebilir mi?

Yanıtlar:


54

EDIT: Fiziksel menü düğmesinin durumuna cevap vermek için değiştirildi.

Bu aslında tasarım tarafından önlenir. Android Tasarım Kılavuzu'nun Uyumluluk Bölümü'ne göre ,

"... eylem taşması menü donanım anahtarından elde edilebilir. Sonuçta ortaya çıkan eylemler açılır ... ekranın altında görüntülenir."

Ekran görüntülerinde, fiziksel menü düğmeli telefonların ActionBar'da taşma menüsü olmadığına dikkat edin. Bu, kullanıcı için belirsizliği önler, esas olarak aynı menüyü açmak için iki düğme bulunur.

Cihazlar arasında tutarlılık konusunu ele almak için: Sonuçta, kullanıcı deneyimi için uygulamanızın aynı cihazdaki diğer tüm uygulamalarla tutarlı bir şekilde davranması, tüm cihazlarda kendisi ile tutarlı bir şekilde davranmasından daha önemlidir.


1
Alexander - Hayır, tüm showAsAction değerlerini ve çeşitli kombinasyonları denedim ve hiçbiri hile yapmıyor (en azından emülatörde). İşlem çubuğundaki taşma menüsü, yalnızca bir menü düğmesi olmayan bir cihazı taklit edersem görünür . O dikey üç nokta görmek istiyorum ve taşan öğeleri cihazlarda burada gösterilir var olan bir menü düğmesi. Bunu biraz daha açık hale getirmek için sorumu düzenledim.
PaulP

41
Bu konuşmaya adım atalım ve tartışalım: Tasarım tarafından engellendiğini biliyorum (tasarım yönergelerini okudum). Ama bence bu% $ /% # +. Örneğin: kullanıcı bir Galaxy Nexus'tan (-> w Taşma) Nexus One'a (w 4.0 / -> Taşma yok) geçiyor. Eminim kullanıcı artık menü öğelerini bulamaz. Bu nedenle tüm cihazlar için aynı kullanımı istiyorum. Sonunda, paulp ile aynı problemle bitiyorum. Temiz bir geçici çözüm yok mu?
Sprigg

10
Önce Tasarım Kılavuzunu da okudum. Bana göre bu, destek paketinde kötü bir tasarım seçeneğiydi. Kullanıcıların düğmeden AWAY'a geçişi için daha iyi bir strateji (amaç, değil mi?) Gereksiz hale getirmek, işlevselliği hem ekrana hem de düğmeye koymak olacaktır. Artık işler olduğu gibi, düğme tüm menü seçeneklerini listelemiyor, sadece eylem çubuğunda olmayanları listeliyor, bu nedenle bu tasarım ne eylem çubuğuna düzgün bir geçişi desteklemiyor ne de bir eylem çubuğu eklemeden önce ne yaptığını yapmıyor ( tüm menüyü görüntüle) seçenek). Haklı olduğunuzu ve basit bir çözüm olmadığını sanıyorum.
PaulP

18
Google, yeni Google + uygulamalarında buna karşı çıkıyor. Cihazdan bağımsız olarak taşma öğesi var ... ama yine de geliştiricilerin bildiklerime aynısını yapmalarını ve tavsiyelerde bulunmalarını önlüyorlar.
Karl

10
Dürüst olmak gerekirse, çok fazla kullanıcı onları beklemek için menü sabit anahtar denemek değil yolu gördüm. Tasarım, herhangi bir telefondaki herhangi bir kullanıcının menü seçeneklerinin var olduğunu gösteren bir ekran göstergesine sahip olmaması gerektiğini söylüyorsa, bu tasarım zayıf bir şekilde bilgilendirilir.
Lance Nanek

323

Bu küçük hack'i burada da kullanabilirsiniz:

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) {
}

Koymak için iyi bir yer onCreate, Uygulama sınıfınızın -Method'u olacaktır .

Uygulamayı taşma menüsünü göstermeye zorlayacaktır. Menü düğmesi yine de çalışır, ancak sağ üst köşedeki menüyü açar.

[Düzenle] Şimdi birkaç kez geldi beri: Bu kesmek sadece ActionBarSherlock için değil Android 3.0'da tanıtılan yerel ActionBar için çalışır. İkincisi, taşma menüsünün gösterilip gösterilmeyeceğine karar vermek için kendi dahili mantığını kullanır. ABS kullanıyorsanız, tüm platformlar <4.0 ABS tarafından işlenir ve bu nedenle mantığına tabi tutulur. Hack, Android 4.0 veya daha üstü tüm cihazlarda çalışmaya devam edecek (Android 3.x'i güvenle yok sayabilirsiniz, çünkü orada bir menü düğmesiyle gerçekten tablet yok).

ABS'de menüyü zorlayacak özel bir ForceOverflow-Theme var, ancak görünüşe göre komplikasyonlar nedeniyle gelecekteki sürümlerde kaldırılacak .


4
Kaynak kodunu inceledim. Belgelenmemiş özelliklerin hazine korusu :) Sadece böyle şeyler için uygulanabilir bir yedeğiniz olduğundan emin olun.
Timo Ohr

4
Çok teşekkürler! Bu gerçekten harika. Taşma işlemine inceleme, hata ayıklama ve eylemleri paylaşmak istedim, ancak Nexus S'de gösterilmiyordu. Kullanıcılar Menü düğmesini bile tıklamaz. Taşma ile kullanıcılar ekstra eylemlerin mevcut olduğunu görürler.
Yuriy Kulikov

4
@Ewoks Buradaki yoruma oldukça geç kaldım, ancak bunu ActionBarCompat'ın en son sürümü ile denedim ve iş DID.
jacobhyphenated

3
Bu Samsung Galaxy S3 ve S4'te çalışıyor, ancak LG G2'de çalışmıyor (taşma menü düğmesini göstermek için kontrolü kodlamakta zorlandıklarından şüpheleniliyor)
DVD

18
Güzel! Eclipse size bunu seçmek için Fieldseçim için 6 farklı ithalat verirse java.lang.reflect.Field;)
Eugene van der Merwe

35

Menümü bu şekilde tanımlayarak (ayrıca örneğimde kullanılan ActionBarSherlock simgesiyle) geçici çözüm için kullanıyorum:

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

Bunun xml'nizde manuel "taşma yönetimi" gerektirebileceğini itiraf ediyorum, ancak bu çözümü faydalı buldum.

Ayrıca, etkinliğinizde taşma menüsünü açmak için cihazı HW düğmesini kullanmaya zorlayabilirsiniz:

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

:-)


2
taşma menüsünü açmak için HW düğmesi nasıl kullanılır?
2014

1
HW düğmesiyle taşma menüsünü açmak için güncellenmiş cevabımı görün. :)
Berťák

11

Destek kitaplığındaki eylem çubuğunu ( android.support.v7.app.ActionBar) kullanıyorsanız aşağıdakileri kullanın:

<?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>

Destek kitaplığını kullanırken bunu da uyguladım ve 3.0 öncesi ve sonrası cihazlarda iyi çalışıyor
leafcutter

7

Bu tür bir yöntem Android Geliştiricileri Tasarım Sistemi tarafından engellenir, ancak bunu geçmenin bir yolunu buldum:

Bunu XML menü dosyanıza ekleyin:

<item android:id="@+id/pick_action_provider"
    android:showAsAction="always"
    android:title="More"
    android:icon="@drawable/ic_action_overflow"
    android:actionProviderClass="com.example.AppPickActionProvider" />

Ardından, 'AppPickActionProvider' adlı bir sınıf oluşturun ve aşağıdaki kodu bu klasöre kopyalayın:

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

Burada gösterildiği gibi, bu yöntemi kullanma ve yalnızca bir alt menü kullanma arasındaki fark nedir: stackoverflow.com/a/14634780/878126 ?
android geliştirici

5

Sanırım Alexander Lucas (ne yazık ki) doğru cevabı verdi, bu yüzden "doğru" olarak işaretliyorum. Buraya eklediğim alternatif cevap , Android Geliştiriciler blogunda bu yeni yayına yeni okuyucuları , önceki seviye 11'den geçiş yaparken kodunuzla nasıl başa çıkacağınıza dair bazı özel önerilerle ilgili konunun tam bir tartışması olarak işaret etmektir. yeni Eylem Çubuğuna.

Hala menü düğmesinin menü düğmesinde fazladan bir "Eylem Taşma" düğmesi gibi davranmadığı bir tasarım hatası olduğuna inanıyorum, cihazlar kullanıcı deneyimini ancak suyunu bu noktada köprünün altından geçirmek için daha iyi bir yol olarak etkinleştirdi.


Tasarım hatası hakkında tamamen aynı fikirdeyim - ve bu sinir bozucu buluyorum!
Paul Hunnisett

1
Google'ın son G + uygulamasında bu kuralı ihlal etmeye başlamaması olmasaydı, bu konuda sizinle aynı fikirdeydim. Ve haklı olarak. Menü düğmesi eski değil, SGS3 gibi yeni cihazlarda bile var. Kalmak için burada, maalesef. Ve kullanılabilirliği ciddi şekilde engelliyor.
Timo Ohr

4

Aradığınız şeyin bu olup olmadığından emin değilim, ancak ActionBar'ın Menüsü içinde bir Alt menü oluşturdum ve simgesini Taşma Menüsünün Simgesine uyacak şekilde ayarladım. Öğelerin otomatik olarak gönderilmesine rağmen, (IE her zaman görünür olanı ve her zaman taşan şeyi seçmeniz gerekir) bana bu yaklaşımın size yardımcı olabileceği anlaşılıyor.


2

Önceden yüklenmiş ICS ile birlikte gelen gmail uygulamasında, birden fazla öğe seçili olduğunda menü düğmesi devre dışı bırakılır. Taşma menüsü, fiziksel menü düğmesi yerine taşma düğmesinin kullanılmasıyla tetiklenmeye "zorlanır". ActionBarSherlock adlı bir taşma menüsünü "zorlamanızı" sağlayan üçüncü taraf bir lib var. Ancak bu yalnızca API seviye 14 veya altı (ICS öncesi) üzerinde çalışır



1

Bu sorun öldüğünde özür dilerim.

İşte hatayı gidermek için yaptım. Düzenlere gittim ve araç çubukları içeren iki tane oluşturdum. Biri sdk sürüm 8 için bir düzen ve diğeri sdk sürüm 21 içindi. 8 sürümünde, sdk 21 düzeninde android.widget.Toolbar kullanırken android.support.v7.widget.Toolbar'ı kullandım.

Sonra aktivitemde araç çubuğunu şişiriyorum. Ben 21 ya da daha yüksek olup olmadığını görmek için sdk kontrol. Daha sonra ilgili düzeni şişiririm. Bu, donanım düğmesini gerçekte tasarladığınız araç çubuğuna eşlemeye zorlar.


0

Yeniyi kullanan herkes için 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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.