Bagaimana cara memperbarui item menu yang ditampilkan di ActionBar?


93

Saya memiliki Aktivitas yang memiliki 2 fragmen. Keduanya adalah ListFragments dan keduanya berkontribusi MenuItems ke Menu. Saya memiliki satu MenuItem yang telah saya setel atribut android: showAsAction agar ditampilkan sebagai tombol di ActionBar. Yang bekerja dengan baik.

Sekarang MenuItem bergantung pada status. Ini adalah opsi menu Jeda / Lanjutkan untuk menjeda dan melanjutkan antrian. Masalah saya adalah saya tidak tahu bagaimana mengatur patung awalnya ketika Fragmen dibuat.

Keadaannya tergantung pada apakah antrian dijeda atau tidak. Jadi saya memiliki AsyncTask yang mendapatkan antrian dan menetapkan boolean (dihentikan sementara) berdasarkan status antrian. Saya memanggil onPrepareOptionsMenu untuk menyetel teks untuk item menu Jeda berdasarkan status antrian terakhir yang diketahui dan ini berfungsi dengan baik jika saya meninggalkan MenuItem di menu sebenarnya. Anda mengetuk ikon menu dan onPrepareOptionsMenu diaktifkan dan menu diperbarui sebelum ditampilkan.

Masalahnya adalah, jika saya meletakkan MenuItem yang sama di ActionBar (showAsAction), bagaimana saya bisa memaksanya untuk memperbarui tanpa harus memanggil onPrepareOptionsMenu? Saya harus dapat melakukan ini karena pada peluncuran pertama aplikasi, saya mengirim permintaan untuk mendapatkan antrian, tetapi tugas kembali setelah ActionBar disiapkan dan ditampilkan. Saya telah membuat penangan di fragmen saya yang dipanggil setiap kali saya mendapatkan pembaruan antrian, tetapi dari sana, bagaimana saya dapat memperbarui teks untuk MenuItem saya di ActionBar? Sepertinya saya tidak bisa menemukan cara untuk mendapatkan Menu yang saat ini disetel untuk memanipulasinya kecuali di onPrepareOptionMenu.

Rob W.

Jawaban:


174

Opsi # 1: Coba invalidateOptionsMenu(). Saya tidak tahu apakah ini akan memaksa menggambar ulang segera bilah tindakan atau tidak.

Opsi # 2: Lihat apakah getActionView()mengembalikan apa pun untuk yang terpengaruh MenuItem. Mungkin showAsActionsaja secara otomatis membuat tampilan tindakan untuk Anda. Jika demikian, Anda mungkin dapat mengaktifkan / menonaktifkannya View.

Sepertinya saya tidak bisa menemukan cara untuk mendapatkan Menu yang saat ini disetel untuk memanipulasinya kecuali di onPrepareOptionMenu.

Anda dapat berpegangan pada Menubenda yang Anda serahkan onCreateOptionsMenu(). Mengutip dokumen :

Anda dapat dengan aman menyimpan menu (dan item apa pun yang dibuat darinya), membuat modifikasi sesuai keinginan, hingga waktu berikutnya onCreateOptionsMenu () dipanggil.


2
Mencoba Opsi # 1 dan ini berhasil. Karena saya mencoba memperbarui UI dalam callback dari utas terpisah, itu membuat pengecualian karena saya sebenarnya tidak berada di utas UI. Untuk mengatasinya, saya membuat sebuah Handler dan mengirimkan pesan refresh ke handler ketika callback saya dipanggil. Tetapi pada akhirnya saya menggunakan getActivity (). InvalidateOptionsMenu () untuk menyegarkan menu.
brockoli

@brockoli: Ah, bagus! Mengingat ungkapan Javadocs untuk metode itu, saya skeptis bahwa itu akan memiliki efek yang diinginkan, meskipun sepertinya itulah alasan mereka menambahkannya ke API Level 11 di tempat pertama. Senang mendengarnya berhasil untuk Anda!
CommonsWare

Aku telah membenturkan kepalaku ke dinding mencoba mencari tahu ini dan itu bekerja seperti pesona!
MinceMan

7
Jika Anda menggunakan pustaka dukungan, gunakan supportInvalidateOptionsMenu()saja
Tim Kist

2
@TimKist, supportInvalidateOptionsMenu()sekarang tidak digunakan lagi; Anda dapat menggunakan dengan aman invalidateOptionsMenu().
Primož Kralj

12

dalam kasus saya: invalidateOptionsMenuhanya menyetel ulang teks ke yang asli, tetapi langsung mengakses item menu dan menulis ulang teks keinginan bekerja tanpa masalah:

if (mnuTopMenuActionBar_ != null) {
    MenuItem mnuPageIndex = mnuTopMenuActionBar_
        .findItem(R.id.menu_magazin_pageOfPage_text);

    if (mnuPageIndex != null) {
        if (getScreenOrientation() == 1) {
            mnuPageIndex.setTitle((i + 1) + " von " + pages);
        }
        else {
            mnuPageIndex.setTitle(
                (i + 1) + " + " + (i + 2) + " " + " von " + pages);
        }
        // invalidateOptionsMenu();
    }
}

Karena komentar di bawah ini, saya dapat mengakses item menu melalui kode berikut:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.magazine_swipe_activity, menu);
    mnuTopMenuActionBar_ = menu;
    return true;
}

Bagaimana Anda menangani tampilan ActionBar mnuTopMenuActionBar_?
Paul Mennega

1
ketika bilah tindakan diinisialisasi, saya menyimpan tampilan ke variabel anggota ... seperti ini: @Override public boolean onCreateOptionsMenu (Menu menu) {MenuInflater inflater = getMenuInflater (); inflater.inflate (R.menu.magazine_swipe_activity, menu); mnuTopMenuActionBar_ = menu; kembali benar; }
cV2

Dengan melakukan itu, Anda dapat mengalami masalah sinkronisasi bukan? Maksudku. Anda tidak tahu PERSIS kapan onCreateOptionMenu akan dijalankan, jadi Anda dapat mencapai bagian kode Anda dengan yang mnuTopMenuActionBar_belum diinisialisasi, bukan? Bagaimana Anda mengatasinya?
acrespo

hei, jika actionbar digunakan (ya, ini dia) metode ini selalu dipanggil, jadi tidak ada masalah dengan itu ... (langsung saat aktivitas dimulai) stackoverflow.com/questions/7705927/…
cV2

11

Untuk menyegarkan menu dari Fragment cukup panggil:

getActivity().invalidateOptionsMenu();

4

Saya telah menggunakan kode ini:

public boolean onPrepareOptionsMenu (Menu menu) {       
    MenuInflater inflater = getMenuInflater();
    TextView title  = (TextView) findViewById(R.id.title);
    menu.getItem(0).setTitle(
        getString(R.string.payFor) + " " + title.getText().toString());
    menu.getItem(1).setTitle(getString(R.string.payFor) + "...");
    return true;        
}

Dan bekerja seperti pesona bagi saya, Anda dapat menemukan OnPrepareOptionsMenu di sini


4
Apa tujuan dari MenuInflater di sini?
IgorGanapolsky

Ini brilian
Steve Kamau

2

Pertama, harap ikuti dua baris kode untuk memperbarui item bilah tindakan sebelum Anda harus menyetel kondisi di oncreateOptionMenu (). Sebagai contoh:

Boolean mISQuizItemSelected = false;

/**
 * Called to inflate the action bar menus
 *
 * @param menu
 *      the menu
 *
 * @return true, if successful
 */

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu items for use in the action bar

    inflater.inflate(R.menu.menu_demo, menu);

    //condition to hide the menus
    if (mISQuizItemSelected) {
        for (int i = 0; i < menu.size(); i++) {
            menu.getItem(i).setVisible(false);
        }
    }

    return super.onCreateOptionsMenu(menu);
}

/**
 * Called when the item on the action bar being selected.
 *
 * @param item
 *      menuitem being selected
 *
 * @return true if the menuitem id being selected is matched
 * false if none of the menuitems id are matched
 */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getId() == R.id.action_quiz) {
        //to navigate based on the usertype either learner or leo
        mISQuizItemSelected = true;

        ActionBar actionBar = getActionBar();
        invalidateOptionMenu();
    }
}

1

Untuk kejelasan, saya pikir contoh langsung dari mengambil ke sumber daya dapat ditunjukkan dari berikut ini yang menurut saya berkontribusi pada tanggapan untuk pertanyaan ini dengan contoh langsung yang cepat.

private MenuItem menuItem_;

@Override
public boolean onCreateOptionsMenu(Menu menuF) 
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_layout, menuF);
    menuItem_ = menuF.findItem(R.id.menu_item_identifier);
    return true;
}

Dalam hal ini Anda memegang referensi MenuItem di awal dan kemudian mengubah statusnya (untuk perubahan status ikon misalnya) pada titik waktu tertentu nanti.


-1

Di Kotlin 1.2 cukup panggil:

invalidateOptionsMenu()

dan onCreateOptionsMenufungsinya akan dipanggil lagi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.