จะอัพเดตรายการเมนูที่แสดงใน ActionBar ได้อย่างไร?


94

ฉันมีกิจกรรมที่มีเศษ 2 ส่วน ทั้งสองเป็น ListFragments และทั้งสองมีส่วนร่วม MenuItems ไปยังเมนู ฉันมี MenuItem รายการหนึ่งที่ฉันได้ตั้งค่าแอตทริบิวต์ android: showAsAction ให้แสดงเป็นปุ่มบน ActionBar ซึ่งใช้งานได้ดี

ตอนนี้ MenuItem ขึ้นอยู่กับสถานะ เป็นตัวเลือกเมนู Pause / Resume สำหรับหยุดชั่วคราวและกลับมาทำคิวต่อ ปัญหาของฉันคือฉันไม่สามารถหาวิธีตั้งค่ารูปปั้นเริ่มต้นเมื่อสร้าง Fragment

สถานะขึ้นอยู่กับว่าคิวหยุดชั่วคราวหรือไม่ ดังนั้นฉันจึงมี AsyncTask ที่รับคิวและตั้งค่าบูลีน (หยุดชั่วคราว) ตามสถานะของคิว ฉันกำลังเรียกใช้ onPrepareOptionsMenu เพื่อตั้งค่าข้อความสำหรับรายการเมนูหยุดชั่วคราวตามสถานะสุดท้ายที่ทราบของคิวและจะใช้งานได้ดีถ้าฉันออกจาก MenuItem ในเมนูจริง คุณแตะไอคอนเมนูและ onPrepareOptionsMenu จะเริ่มทำงานและเมนูจะได้รับการอัปเดตก่อนที่จะแสดง

ปัญหาคือถ้าฉันใส่ MenuItem เดียวกันบน ActionBar (showAsAction) ฉันจะบังคับให้อัปเดตโดยไม่ต้องเรียก onPrepareOptionsMenu ได้อย่างไร ฉันต้องสามารถทำได้เพราะในการเปิดตัวแอปครั้งแรกฉันส่งคำขอเพื่อรับคิว แต่งานจะกลับมาหลังจากที่ ActionBar ถูกตั้งค่าและแสดง ฉันได้สร้างตัวจัดการในส่วนของฉันที่ถูกเรียกทุกครั้งที่ฉันได้รับการอัปเดตคิว แต่จากตรงนั้นฉันจะอัปเดตข้อความสำหรับ MenuItem บน ActionBar ได้อย่างไร ดูเหมือนฉันจะหาวิธีรับ set Menu เพื่อจัดการกับมันไม่ได้เลยยกเว้นใน onPrepareOptionMenu

Rob W.

คำตอบ:


175

ตัวเลือก # 1: invalidateOptionsMenu()ลอง ฉันไม่รู้ว่าสิ่งนี้จะบังคับให้มีการวาดใหม่ทันทีของแถบการกระทำหรือไม่

ตัวเลือก # 2: ดูว่าgetActionView()ส่งคืนสิ่งใดสำหรับผู้ได้รับผลกระทบMenuItemหรือไม่ เป็นไปได้ที่showAsActionจะสร้างมุมมองการดำเนินการให้คุณโดยอัตโนมัติ หากเป็นเช่นนั้นคุณสามารถเปิด / ปิดการใช้งานViewได้

ดูเหมือนฉันจะหาวิธีรับ set Menu เพื่อจัดการมันไม่ได้เลยยกเว้นใน onPrepareOptionMenu

คุณสามารถแขวนMenuสิ่งของที่คุณส่งonCreateOptionsMenu()มาได้ อ้างถึงเอกสาร :

คุณสามารถถือเมนูได้อย่างปลอดภัย (และรายการใด ๆ ที่สร้างจากเมนูนั้น) ทำการปรับเปลี่ยนตามต้องการจนกว่าจะมีการเรียก onCreateOptionsMenu () ในครั้งถัดไป


2
พยายามตัวเลือก # 1 และนี่ก็เป็นเคล็ดลับ เนื่องจากฉันพยายามอัปเดต UI ในการเรียกกลับจากเธรดแยกต่างหากจึงมีข้อยกเว้นเนื่องจากฉันไม่ได้อยู่ในเธรด UI ในการแก้ไขปัญหานี้ฉันได้สร้างตัวจัดการและส่งข้อความรีเฟรชไปยังตัวจัดการเมื่อมีการเรียกกลับ แต่ในที่สุดฉันก็ใช้ getActivity (). invalidateOptionsMenu () เพื่อรีเฟรชเมนู
brockoli

@brockoli: อาดี! จากการใช้วลี Javadocs สำหรับวิธีการนั้นฉันไม่แน่ใจว่ามันจะมีผลตามที่ต้องการแม้ว่ามันจะดูเหมือนว่าเป็นเหตุผลที่พวกเขาเพิ่มเข้าไปใน API ระดับ 11 ในตอนแรก ดีใจที่ได้ยินว่ามันใช้ได้ผลสำหรับคุณ!
CommonsWare

ฉันเอาหัวโขกกับกำแพงพยายามคิดออกและมันก็เหมือนมีเสน่ห์!
MinceMan

7
หากคุณกำลังใช้ไลบรารีสนับสนุนให้ใช้supportInvalidateOptionsMenu()แทน
Tim Kist

2
@TimKist supportInvalidateOptionsMenu()เลิกใช้แล้ว; invalidateOptionsMenu()คุณสามารถใช้
Primož Kralj

12

ในกรณีของฉัน: invalidateOptionsMenuเพียงแค่ตั้งค่าข้อความใหม่ให้เป็นต้นฉบับ แต่การเข้าถึงรายการเมนูโดยตรงและการเขียนข้อความปรารถนาอีกครั้งทำงานได้โดยไม่มีปัญหา:

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

เนื่องจากความคิดเห็นด้านล่างฉันสามารถเข้าถึงรายการเมนูผ่านรหัสต่อไปนี้:

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

คุณจัดการกับมุมมอง ActionBar ได้mnuTopMenuActionBar_อย่างไร?
Paul Mennega

1
เมื่อเริ่มต้นแถบการดำเนินการฉันจะบันทึกมุมมองลงในตัวแปรสมาชิก ... ดังนี้: @Override บูลีนสาธารณะ onCreateOptionsMenu (เมนูเมนู) {MenuInflater inflater = getMenuInflater (); inflater.inflate (R.menu.magazine_swipe_activity เมนู); mnuTopMenuActionBar_ = เมนู; กลับจริง; }
cV2

เมื่อทำเช่นนั้นคุณจะมีปัญหาในการซิงโครไนซ์ได้ใช่ไหม ฉันหมายถึง. คุณไม่ทราบแน่ชัดว่า onCreateOptionMenu กำลังจะทำงานดังนั้นคุณอาจไปถึงชิ้นส่วนของรหัสของคุณโดยmnuTopMenuActionBar_ไม่ได้กำหนดค่าเริ่มต้นใช่ไหม? คุณจะแก้ไขปัญหานั้นอย่างไร?
เอเคอร์

เฮ้ถ้ามีการใช้ actionbar (ใช่นี่คือ) วิธีนี้จะถูกเรียกเสมอดังนั้นจึงไม่มีปัญหากับสิ่งนั้น ... (โดยตรงที่จุดเริ่มต้นกิจกรรม) stackoverflow.com/questions/7705927/…
cV2


4

ฉันใช้รหัสนี้:

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

และทำงานได้อย่างมีเสน่ห์สำหรับฉันคุณสามารถค้นหา OnPrepareOptionsMenu ได้ที่นี่


4
MenuInflater มีจุดประสงค์อะไรที่นี่?
IgorGanapolsky

ยอดเยี่ยมมาก
Steve Kamau

2

ขั้นแรกโปรดปฏิบัติตามรหัสสองบรรทัดเพื่ออัปเดตรายการแถบการดำเนินการก่อนหน้านั้นคุณควรตั้งเงื่อนไขใน oncreateOptionMenu () ตัวอย่างเช่น:

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

เพื่อความชัดเจนฉันคิดว่าตัวอย่างโดยตรงของการคว้าทรัพยากรสามารถแสดงได้จากสิ่งต่อไปนี้ที่ฉันคิดว่ามีส่วนช่วยในการตอบคำถามนี้ด้วยตัวอย่างโดยตรงอย่างรวดเร็ว

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

ในกรณีนี้คุณยึดการอ้างอิง MenuItem ไว้ที่จุดเริ่มต้นจากนั้นเปลี่ยนสถานะ (สำหรับการเปลี่ยนแปลงสถานะไอคอน) ในเวลาต่อมา


-1

ในKotlin 1.2เพียงแค่โทร:

invalidateOptionsMenu()

และonCreateOptionsMenuฟังก์ชันจะถูกเรียกใช้อีกครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.