Android: Düğme tıklamasında seçenek menüsü öğesi nasıl etkinleştirilir / devre dışı bırakılır?


127

Yöntemleri onCreateOptionsMenuveya kullandığım zamanlarda kolaylıkla yapabilirim onOptionsItemSelected.

Ancak ekranın herhangi bir yerinde bir düğme var ve bu düğmeye tıkladığımda, içerik menüsü öğelerini etkinleştirmeli / devre dışı bırakmalı.

Yanıtlar:


272

Her neyse, belgeler her şeyi kapsar.

Çalışma zamanında menü öğelerini değiştirme

Aktivite oluşturulduktan sonra, onCreateOptionsMenu()yöntem yukarıda açıklandığı gibi yalnızca bir kez çağrılır. Sistem Menu, faaliyetiniz yok olana kadar bu yöntemde tanımladığınız şeyi tutar ve yeniden kullanır . Seçenekler Menüsünü ilk oluşturulduktan sonra değiştirmek isterseniz, onPrepareOptionsMenu()yöntemi geçersiz kılmalısınız. Bu size şu anda var olduğu şekliyle Menu nesnesini iletir. Uygulamanızın mevcut durumuna bağlı olarak menü öğelerini kaldırmak, eklemek, devre dışı bırakmak veya etkinleştirmek istiyorsanız bu yararlıdır.

Örneğin

@Override
public boolean onPrepareOptionsMenu (Menu menu) {
    if (isFinalized) {
        menu.getItem(1).setEnabled(false);
        // You can also use something like:
        // menu.findItem(R.id.example_foobar).setEnabled(false);
    }
    return true;
}

Android 3.0 ve sonraki sürümlerde, eylem çubuğunda menü öğeleri sunulduğunda seçenekler menüsünün her zaman açık olduğu kabul edilir. Bir olay meydana geldiğinde ve bir menü güncellemesi yapmak istediğinizde invalidateOptionsMenu(), sistem çağrısını talep etmek için aramanız gerekir onPrepareOptionsMenu().


2
setEnable()Bu menüye bastığınızda ne olacağını değiştiriyor, ancak görünüşünü değiştirmiyor (sorun ne, Android geliştiricileri?). Bu nedenle, başlığı devre dışı bırakmak ve değiştirmek ya da tercihen sadece MenuItemgörünmez yapmak daha açıktır .
Vlad

19
Hızlı ipucu: falsemenüyü tamamen devre dışı bırakmak için geri dönün .
Bart Friederichs

5
Ayrıca, onPrepareOptionsMenu'daki API yorumu açıkça şunu belirtir: Türetilen sınıflar her zaman (!) Temel sınıf uygulamasına çağrı yapmalıdır. Süper çağrınızı orada unuttunuz.
AgentKnopf


Çalışma zamanında eklenen MenuItem'in tamsayı kimliğini nasıl biliyorsunuz? Bunları yalnızca isme göre ekleyebilirsiniz.
Antonio Sesto

66

Tüm android sürümlerinde, en kolay yol: bunu, bir menü eylem simgesini devre dışı olarak GÖSTERMEK VE devre dışı olarak FONKSİYON yapmak için kullanın:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    MenuItem item = menu.findItem(R.id.menu_my_item);

    if (myItemShouldBeEnabled) {
        item.setEnabled(true);
        item.getIcon().setAlpha(255);
    } else {
        // disabled
        item.setEnabled(false);
        item.getIcon().setAlpha(130);
    }
}

1
Görünürlüğü yanlış olarak ayarlayabildiğiniz halde neden alfa'yı 0'a ayarlayasınız?
MLProgrammer-CiM

8
Alfa'yı 0'a
Frank

8
Düğmenin bağlamına bağlıdır. Düğmenin normalde sunacağı özellik mevcut durumda tamamen kullanılamazsa, evet, görünürlük görünmez / gitmiş olmalıdır. Bununla birlikte, düğme normalde hizmet verecekse, herhangi bir nedenle (örneğin, kullanıcı premium üye olursa, kullanıcı oturum açarsa, kullanıcı internete bağlanırsa vb.) Kullanılabilir OLABİLİR OLABİLİR çünkü o zaman kullanıcının herhangi bir nedenle erişemeyecekleri bazı mevcut özellikler olduğunu bilmesini sağlar.
yiati

6
Simgeyi görünmez olarak ayarlamak, neredeyse tüm kullanım durumlarında daha iyi değildir. Bir grubunuz olması durumunda, konumlarında kalmaları daha iyidir ve grileşmesi, kullanıcıya belirli bir program durumunda etkinleştirilebilecek bir seçenek olduğunu gösterir. bir şeyi görünmez ve görünmez yapmak ve muhtemelen düzen değişikliklerine neden olmak çok saçma. Çoğu menünün öğeleri griye çevirmesinin ve moda bağlı olarak bunları kaldırmamasının bir nedeni vardır.
RichieHH

1
Menüde simge yoksa nasıl olur? AyarlayamazsınızAlpha ().
Latief Anwar

42

Seçenek menüsünü oluştururken öğeyi değişken olarak kaydedebilir ve ardından özelliklerini istediğiniz gibi değiştirebilirsiniz.

private MenuItem securedConnection;
private MenuItem insecuredConnection;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.connect_menu, menu);
    securedConnection = menu.getItem(0);
    insecuredConnection =  menu.getItem(1);
    return true;
}

public void foo(){
       securedConnection.setEnabled(true);
}    

Bu, herhangi bir Android sürümüne verilen doğru yanıttır. Doğrulanmış yanıt yalnızca API 11> cihazlar için geçerlidir.
Marco HC

2
Bunu denedim ve işe yaramıyor. Şunu mu demek istediniz onPrepareOptionsMenu?
Christopher Pickslay

6

@Vikas sürümünü sadeleştirin

@Override
public boolean onPrepareOptionsMenu (Menu menu) {

    menu.findItem(R.id.example_foobar).setEnabled(isFinalized);
    return true;
}

5

Bir AsyncTask yapıldığında öğeleri etkinleştirmek veya devre dışı bırakmak için mevcut menüyü güncelleme.

Kullanım durumumda, AsyncTask'ım verileri yüklerken menümü devre dışı bırakmam gerekiyordu, ardından tüm verileri yükledikten sonra, kullanıcının kullanmasına izin vermek için tüm menüyü tekrar etkinleştirmem gerekiyordu.

Bu, uygulamanın veri yüklenirken kullanıcıların menü öğelerine tıklamasına izin vermesini engelledi.

Öncelikle bir durum değişkeni tanımlıyorum, değişken 0 ise menü gösteriliyor, bu değişken 1 ise menü gizli.

private mMenuState = 1; //I initialize it on 1 since I need all elements to be hidden when my activity starts loading.

Sonra onCreateOptionsMenu()bu değişkeni kontrol ediyorum, eğer 1 ise tüm öğelerimi devre dışı bırakıyorum, değilse, sadece hepsini gösteriyorum

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.menu_galeria_pictos, menu);

        if(mMenuState==1){
            for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(false);
            }
        }else{
             for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(true);
            }
        }

        return super.onCreateOptionsMenu(menu);
    }

Şimdi, Aktivitem başladığında, onCreateOptionsMenu()sadece bir kez çağrılacak ve tüm öğelerim gitmiş olacak çünkü başlangıçta onlar için durumu ayarlıyorum.

Sonra bir AsyncTask oluşturuyorum. Burada bu durum değişkenini 0 olarak ayarlıyorum. onPostExecute()

Bu adım çok önemli!

Aradığınızda invalidateOptionsMenu();yeniden başlayacakonCreateOptionsMenu();

Yani, durumumu 0 olarak ayarladıktan sonra, tüm menüyü yeniden çiziyorum ama bu sefer 0'daki değişkenimle, yani tüm asenkron işlem tamamlandıktan sonra tüm menü gösterilecek ve ardından kullanıcım menüyü kullanabilir .

 public class LoadMyGroups extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mMenuState = 1; //you can set here the state of the menu too if you dont want to initialize it at global declaration. 

        }

        @Override
        protected Void doInBackground(Void... voids) {
           //Background work

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            mMenuState=0; //We change the state and relaunch onCreateOptionsMenu
            invalidateOptionsMenu(); //Relaunch onCreateOptionsMenu

        }
    }

Sonuçlar

görüntü açıklamasını buraya girin


2

gezinme çekmecesinde çalışırken en iyi çözüm

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.setGroupVisible(0,false);
        return true;
    }

Bu, tüm menüyü gizler ve tekrar açmayı imkansız kılar
MrStahlfelge

2

Eski bir soru için daha modern bir cevap:

MainActivity.kt

private var myMenuIconEnabled by Delegates.observable(true) { _, old, new ->
    if (new != old) invalidateOptionsMenu()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    findViewById<Button>(R.id.my_button).setOnClickListener { myMenuIconEnabled = false }
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_main_activity, menu)
    return super.onCreateOptionsMenu(menu)
}

override fun onPrepareOptionsMenu(menu: Menu): Boolean {
    menu.findItem(R.id.action_my_action).isEnabled = myMenuIconEnabled
    return super.onPrepareOptionsMenu(menu)
}

menu_main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/action_my_action"
    android:icon="@drawable/ic_my_icon_24dp"
    app:iconTint="@drawable/menu_item_icon_selector"
    android:title="My title"
    app:showAsAction="always" />
</menu>

menu_item_icon_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?enabledMenuIconColor" android:state_enabled="true" />
<item android:color="?disabledMenuIconColor" />

attrs.xml

<resources>   
    <attr name="enabledMenuIconColor" format="reference|color"/>
    <attr name="disabledMenuIconColor" format="reference|color"/>
</resources>

styles.xml or themes.xml

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="disabledMenuIconColor">@color/white_30_alpha</item>
    <item name="enabledMenuIconColor">@android:color/white</item>

Uygulamanın her yerinde çok fazla standart metin olmadan kullanılabilecek harika bir yaklaşım.
Arthur

Ne problemin var?
ExpensiveBelly

@ExpensiveBelly kendi başına bir sorun değil, sadece kamuoyuna duyurulur.
Big McLargeHuge

1
  @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

                case R.id.item_id:

                       //Your Code....

                        item.setEnabled(false);
                        break;
              }
            return super.onOptionsItemSelected(item);
     }

Yorumdan: Merhaba, lütfen sadece kaynak kodu ile cevap vermeyin. Çözümünüzün nasıl çalıştığı hakkında güzel bir açıklama sağlamaya çalışın. Bakınız: Nasıl iyi bir cevap yazabilirim? . Teşekkürler
sɐunıɔ ןɐ qɐp

1

Yaptığım şey, adresindeki Menüye bir referans kaydetmekti onCreateOptionsMenu. Bu, nir'in cevabına benzer, ancak her bir öğeyi tek tek kaydetmek yerine tüm menüyü kaydettim.

Bir Menü bildirin Menu toolbarMenu;.

Ardından onCreateOptionsMenumenüyü değişkeninize kaydedin

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    getMenuInflater().inflate(R.menu.main_menu, menu);
    toolbarMenu = menu;
    return true;
}

Artık menünüze ve tüm öğelerine istediğiniz zaman erişebilirsiniz. toolbarMenu.getItem(0).setEnabled(false);


0
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    // getMenuInflater().inflate(R.menu.home, menu);
    return false;
}

2
Bu kod OP'nin sorusunu yanıtlasa da, birkaç kelime açıklama, mevcut ve gelecekteki kullanıcıların yanıtınızı daha iyi anlamalarına yardımcı olacaktır.
Thom

0

Görünüyorsa menü

menu.findItem(R.id.id_name).setVisible(true);

Menüyü gizle

menu.findItem(R.id.id_name).setVisible(false);

-4

Genel olarak, çalışma zamanında görünümlerinizin özelliklerini değiştirebilir:

(Button) item = (Button) findViewById(R.id.idBut);

ve sonra...

item.setVisibility(false)

fakat

ContextMenu'den seçeneklerin de görünürlüğünü değiştirmek istiyorsanız, düğmenize basarak bir bayrağı etkinleştirebilir ve ardından onCreateContextMenu'de bunun gibi bir şey yapabilirsiniz:

 @Override
        public void onCreateContextMenu(ContextMenu menu, 
                View v,ContextMenu.ContextMenuInfo menuInfo) {

            super.onCreateContextMenu(menu, v, menuInfo);

                menu.setHeaderTitle(R.string.context_title);

                if (flagIsOn()) {
                    addMenuItem(menu, "Option available", true);
                } else {
                    Toast.makeText(this, "Option not available", 500).show();
                }

        }

Umarım bu yardımcı olur


Yanlış anladığınızı söylemeliyim, Button değil, menü öğesinin devre dışı bırakılmasını istiyorum.
Vikas

cevabım tamamlandı. Bu kod işe yarıyor, projelerimde kullandım
Eric

1
Çalıştığınız için teşekkürler, ancak onCreateContextMenuyöntemde değiştirebileceğimi daha önce belirttiğim soruyu doğru okumalısınız . Ancak bu yöntemden bağlam menüsüne dışarıdan erişmek istiyorum.
Vikas

onCreateContextMenusadece bir kez çağrılacak, ancak menü öğesini etkinleştirmek / devre dışı bırakmak için düğmeye birçok kez tıklayabilirim.
Vikas

Evet, ancak içerik menüsü normalde gizlenecek şekilde yapılır. 'Bir yer düğmesine' basarsanız ve bayrağı dediğim gibi ayarlarsanız, bu içerik menüsü görünmez ve içerik menünüzü bir sonraki yeniden yüklediğinizde bu seçenek görünmez olacaktır. Diğer bir seçenek de, olayları başka yöntemlerle işlemek için aynı görünüme sahip başka bir menü türü yapmaktır.
Eric
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.