Android: Cara mengaktifkan / menonaktifkan item menu opsi pada klik tombol?

127

Saya dapat dengan mudah melakukannya ketika saya menggunakan onCreateOptionsMenuatau onOptionsItemSelectedmetode.

Tapi saya memiliki tombol di suatu tempat di layar, dan mengklik tombol itu, itu harus mengaktifkan / menonaktifkan item menu konteks.

Vara
sumber

Jawaban:

272

Bagaimanapun, dokumentasi mencakup semua hal.

Mengubah item menu saat runtime

Setelah aktivitas dibuat, onCreateOptionsMenu()metode ini dipanggil hanya sekali, seperti dijelaskan di atas. Sistem menyimpan dan menggunakan kembali yang MenuAnda tetapkan dalam metode ini hingga aktivitas Anda dihancurkan. Jika Anda ingin mengubah Menu Opsi kapan saja setelah pertama kali dibuat, Anda harus mengganti onPrepareOptionsMenu()metode. Ini memberi Anda objek Menu seperti yang ada saat ini. Ini berguna jika Anda ingin menghapus, menambah, menonaktifkan, atau mengaktifkan item menu tergantung pada kondisi aplikasi Anda saat ini.

Misalnya

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

Pada Android 3.0 dan lebih tinggi, menu opsi dianggap selalu terbuka ketika item menu disajikan di panel tindakan. Ketika suatu peristiwa terjadi dan Anda ingin melakukan pembaruan menu, Anda harus menelepon invalidateOptionsMenu()untuk meminta panggilan sistem onPrepareOptionsMenu().

Vara
sumber
2
setEnable()tidak mengubah apa yang terjadi ketika Anda menekan menu ini tetapi tidak mengubah tampilannya (apa yang salah, pengembang Android?). Jadi lebih jelas untuk menonaktifkan dan mengubah judul, atau lebih baik buat yang MenuItemtidak terlihat.
Vlad
19
Kiat cepat: kembali falseuntuk menonaktifkan menu sepenuhnya.
Bart Friederichs
5
Ditambah komentar API pada onPrepareOptionsMenu dengan jelas menyatakan: Turunkan kelas harus selalu (!) Memanggil ke implementasi kelas dasar. Anda lupa panggilan super Anda di sana.
AgentKnopf
Bagaimana Anda tahu ID bilangan bulat dari MenuItem ditambahkan saat run-time? Anda hanya dapat menambahkannya dengan nama.
Antonio Sesto
66

Pada semua versi Android, cara termudah: gunakan ini untuk MENUNJUKKAN ikon tindakan menu sebagai dinonaktifkan DAN menjadikannya FUNGSI juga dinonaktifkan:

@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);
    }
}
jujur
sumber
1
Mengapa mengatur alpha ke 0 saat Anda dapat mengatur visibilitas ke false?
MLProgrammer-CiM
8
Saya tidak mengatur alpha ke 0, tetapi ke 130.
Frank
8
Tergantung pada konteks tombolnya. Jika fitur tombol biasanya akan berfungsi benar-benar tidak dapat digunakan dalam keadaan saat ini, maka ya visibilitas harus tidak terlihat / hilang. Namun, jika fitur tombol biasanya dapat digunakan dapat digunakan dengan alasan apa pun (mis. Jika pengguna menjadi anggota premium, jika pengguna masuk, jika pengguna terhubung ke internet, dll.) Maka itu bagus untuk membuatnya diklik. karena dengan begitu ia memberi tahu pengguna ada beberapa fitur yang tidak dapat mereka akses karena suatu alasan.
yiati
6
Mengatur ikon agar tidak terlihat tidak lebih baik di hampir semua kasus penggunaan. Jika Anda memiliki grup yang lebih baik mereka tetap di posisi mereka dan diklik menunjukkan kepada pengguna bahwa ada opsi yang dapat diaktifkan dalam keadaan program tertentu. membuat sesuatu tidak terlihat dan tidak terlihat dan mungkin menyebabkan perubahan tata letak sangat konyol. Ada alasan mengapa sebagian besar menu menghapus item dan tidak menghapusnya tergantung mode.
RichieHH
1
Bagaimana jika menu tidak mengandung ikon? Anda tidak dapat mengaturAlpha ().
Latief Anwar
42

Anda bisa menyimpan item sebagai variabel saat membuat menu opsi dan kemudian mengubah propertinya sesuka hati.

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);
}    
nir
sumber
Itu adalah respons yang benar untuk semua versi Android. Respons yang divalidasi hanya valid untuk perangkat API 11>.
Marco HC
2
Saya sudah mencoba ini, dan itu tidak berhasil. Apakah maksud Anda onPrepareOptionsMenu?
Christopher Pickslay
6

menyederhanakan versi @Vikas

@Override
public boolean onPrepareOptionsMenu (Menu menu) {

    menu.findItem(R.id.example_foobar).setEnabled(isFinalized);
    return true;
}
Kosrat D. Ahmad
sumber
4

Cara memperbarui menu saat ini untuk mengaktifkan atau menonaktifkan item ketika AsyncTask dilakukan.

Dalam kasus penggunaan saya, saya perlu menonaktifkan menu saya ketika AsyncTask saya sedang memuat data, kemudian setelah memuat semua data, saya perlu mengaktifkan semua menu lagi agar pengguna dapat menggunakannya.

Ini mencegah aplikasi untuk membiarkan pengguna mengklik item menu saat data sedang dimuat.

Pertama, saya mendeklarasikan variabel status, jika variabelnya adalah 0 maka menu akan ditampilkan, jika variabel itu adalah 1 maka menu akan disembunyikan.

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

Kemudian di saya, onCreateOptionsMenu()saya memeriksa variabel ini, jika 1 saya menonaktifkan semua item saya, jika tidak, saya hanya menunjukkan semuanya

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

Sekarang, ketika Aktivitas saya dimulai, onCreateOptionsMenu()akan dipanggil sekali saja, dan semua barang saya akan hilang karena saya mengatur keadaan untuk mereka di awal.

Lalu saya membuat AsyncTask Di mana saya mengatur variabel status ke 0 di saya onPostExecute()

Langkah ini sangat penting!

Ketika Anda memanggilnya invalidateOptionsMenu();akan diluncurkan kembalionCreateOptionsMenu();

Jadi, setelah mengatur status saya ke 0, saya hanya menggambar ulang semua menu tapi kali ini dengan variabel saya pada 0, yang mengatakan, semua menu akan ditampilkan setelah semua proses asinkron dilakukan, dan kemudian pengguna saya dapat menggunakan menu .

 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

        }
    }

Hasil

masukkan deskripsi gambar di sini

Gastón Saillén
sumber
2

solusi terbaik saat Anda tampil di laci navigasi

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.setGroupVisible(0,false);
        return true;
    }
Prashant Gosai
sumber
Ini menyembunyikan seluruh menu dan membuatnya tidak mungkin untuk membukanya lagi
MrStahlfelge
2

Jawaban yang lebih modern untuk pertanyaan lama:

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>
Belly yang mahal
sumber
Pendekatan hebat yang bisa digunakan tanpa banyak ketel di sekitar aplikasi.
Arthur
Apa masalah yang Anda hadapi?
ExpensiveBelly
@ExpensiveBelly bukan masalah saja, hanya pemberitahuan publik.
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);
     }
Tousif Akram
sumber
Dari Ulasan: Hai, tolong jangan jawab hanya dengan kode sumber. Cobalah untuk memberikan deskripsi yang bagus tentang cara kerja solusi Anda. Lihat: Bagaimana saya menulis jawaban yang baik? . Terima kasih
sɐunıɔ ןɐ qɐp
1

Apa yang saya lakukan adalah menyimpan referensi ke Menu di onCreateOptionsMenu. Ini mirip dengan jawaban nir kecuali alih-alih menyimpan setiap item, saya menyimpan seluruh menu.

Deklarasikan Menu Menu toolbarMenu;.

Kemudian di onCreateOptionsMenusimpan menu ke variabel Anda

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

Sekarang Anda dapat mengakses menu Anda dan semua itemnya kapan saja Anda mau. toolbarMenu.getItem(0).setEnabled(false);

Smitty-Werben-Jager-Manjenson
sumber
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;
}
Draken
sumber
2
Sementara kode ini dapat menjawab pertanyaan OP, beberapa kata penjelasan akan membantu pengguna saat ini dan di masa depan memahami respons Anda dengan lebih baik.
Thom
0

Jika terlihat menu

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

Jika sembunyikan menu

menu.findItem(R.id.id_name).setVisible(false);
murugan mani
sumber
-4

Secara umum dapat mengubah properti tampilan Anda di runtime:

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

lalu...

item.setVisibility(false)

tapi

jika Anda ingin memodifikasi visibilitas opsi dari ContextMenu, pada tekan tombol Anda, Anda dapat mengaktifkan bendera, dan kemudian di onCreateContextMenu Anda dapat melakukan sesuatu seperti ini:

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

        }

saya harap ini membantu

Eric
sumber
Saya harus mengatakan Anda salah, saya ingin item menu dinonaktifkan, bukan Button.
Vikas
jawaban saya selesai. Kode ini berfungsi, saya telah menggunakan dalam proyek saya
Eric
1
Terima kasih atas kerja Anda, tetapi Anda harus membaca pertanyaan dengan benar bahwa saya telah menyatakan bahwa saya dapat mengubahnya dengan onCreateContextMenumetode. Tapi saya ingin mengakses menu konteks dari metode ini.
Vikas
onCreateContextMenuakan dipanggil hanya sekali, tetapi saya dapat mengklik tombol banyak waktu untuk mengaktifkan / menonaktifkan item menu.
Vikas
Ya, tetapi menu konteks biasanya dilakukan untuk disembunyikan. Jika Anda menekan 'tombol di suatu tempat' dan mengatur bendera seperti yang saya katakan, menu konteks ini tidak terlihat dan saat berikutnya Anda memuat ulang menu konteks Anda, opsi ini tidak akan terlihat. Pilihan lain adalah melakukan jenis menu lain dengan penampilan yang sama untuk menangani acara dengan metode lain.
Eric