วิธีเปลี่ยนข้อความรายการเมนูแบบไดนามิกใน Android


212

ฉันพยายามเปลี่ยนชื่อของรายการเมนูจากด้านนอกonOptionsItemSelected(MenuItem item)วิธี

ฉันทำสิ่งต่อไปนี้แล้ว

public boolean onOptionsItemSelected(MenuItem item) {
  try {
    switch(item.getItemId()) {
      case R.id.bedSwitch:
        if(item.getTitle().equals("Set to 'In bed'")) {
          item.setTitle("Set to 'Out of bed'");
          inBed = false;
        } else {
          item.setTitle("Set to 'In bed'");
          inBed = true;
        }
        break;
    }
  } catch(Exception e) {
    Log.i("Sleep Recorder", e.toString());
  }
  return true;
}

แต่ฉันต้องการที่จะสามารถปรับเปลี่ยนชื่อของรายการเมนูเฉพาะนอกวิธีนี้


stackoverflow.com/a/32072318/1651286ควรเป็นคำตอบที่ได้รับการยอมรับ
Akhil Dad

คำตอบ:


127

ในฐานะที่เป็น JxDarkAngel ปัญหาเรียกนี้จากที่ใดก็ได้ในของคุณกิจกรรม ,

invalidateOptionsMenu();

แล้วเอาชนะ:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
  MenuItem item = menu.findItem(R.id.bedSwitch);
    if (item.getTitle().equals("Set to 'In bed'")) {
        item.setTitle("Set to 'Out of bed'");
        inBed = false;
    } else {
        item.setTitle("Set to 'In bed'");
        inBed = true;
    }
  return super.onPrepareOptionsMenu(menu);
}

เป็นทางเลือกที่ดีกว่ามาก ฉันใช้คำตอบจากhttps://stackoverflow.com/a/17496503/568197


ทางออกที่ดีที่สุด เพราะวิธีนี้ใช้แทน android แทนการประดิษฐ์ล้อ
Azlan Jamal

เพิ่งทราบว่าonPrepareOptionsMenu()มีการเรียกค่อนข้างบ่อยโดยกรอบ Android เช่นเมื่อแสดงกิจกรรมและทุกครั้งที่มีการแสดงเมนู ดังนั้นสิ่งนี้อาจไม่มีประสิทธิภาพมากนักหากเมนูของคุณไม่เปลี่ยนบ่อยนัก
Mr-IDE

1
invalidateOptionsMenu()นอกจากนี้ยังจะเรียกเพื่อให้คุณสามารถใส่ตรรกะการปรับปรุงในonCreateOptionsMenu() onCreateOptionsMenu()
Mr-IDE

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

@Garbit อัพเดทให้ใช้รหัสของคุณจากคำถามเดิม!
Todd DeLand

375

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

public class YourActivity extends Activity {

  private Menu menu;
  private String inBedMenuTitle = "Set to 'In bed'";
  private String outOfBedMenuTitle = "Set to 'Out of bed'";
  private boolean inBed = false;

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    // Create your menu...

    this.menu = menu;
    return true;
  }

  private void updateMenuTitles() {
    MenuItem bedMenuItem = menu.findItem(R.id.bedSwitch);
    if (inBed) {
      bedMenuItem.setTitle(outOfBedMenuTitle);
    } else {
      bedMenuItem.setTitle(inBedMenuTitle);
    }
  }

}

หรือคุณสามารถแทนที่onPrepareOptionsMenuเพื่ออัปเดตรายการเมนูทุกครั้งที่แสดงเมนู


1
ฉันคาดหวังว่า Android จะมีทางออกที่ดีกว่าสำหรับปัญหาเหล่านี้ ดูเหมือนว่าคำตอบที่ง่ายที่สุดมักจะดีที่สุด - ขอบคุณ
Steven Wolfe

12

คุณสามารถทำสิ่งนี้สร้างวัตถุ "เมนู" ส่วนกลางจากนั้นกำหนดมันใน onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

จากนั้นกำหนดที่นี่

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

จากนั้นใช้วัตถุเมนูที่กำหนดเพื่อรับรายการที่ต้องการ

menu.findItem(R.id.bedSwitch).setTitle("Your Text");

5

สร้างเมธอด setOptionsTitle () และตั้งค่าฟิลด์ในคลาสของคุณ เช่น:

String bedStatus = "Set to 'Out of Bed'";

...

public void setOptionsTitle(String status)
{
    bedStatus = status;

}

ตอนนี้เมื่อเมนูได้รับการเติมเปลี่ยนชื่อเป็นสถานะของคุณ:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(bedStatus);


        // Return true so that the menu gets displayed.
        return true;
    }

ฉันต้องสามารถตั้งค่าได้หลังจากที่กิจกรรมถูกแสดงผล ดังนั้นจึงไม่ได้อยู่ในทั้งสองวิธี
Garbit

โทร setOptionsTitle ณ จุดใด ๆ หลังจากกิจกรรมของคุณถูกแสดงผล ฉันเดาว่าฉันไม่เข้าใจสิ่งที่คุณต้องการเพราะ "ฉันต้องสามารถตั้งค่าได้หลังจากที่กิจกรรมถูกแสดงผล" หมายถึงฉันหลังจากที่คุณเรียก setContent (R.layout.id) คุณอาจต้องเปลี่ยนสิ่งที่ตัวเลือก แสดงเมนู (ซึ่งคุณสามารถทำกับ setOptionsTitle () - จากวิธีใดก็ได้ทุกที่ทุกเวลา)
แจ็ค

แม้ว่าวิธีการนี้จะใช้งานได้ แต่ก็ไม่แนะนำให้ทำเช่นนี้เพราะวัตถุเมนูที่จัดการเมนูจะไม่ทราบว่าเมื่อมีการเปลี่ยนแปลงชื่อเรื่องและดังนั้นจึงไม่สามารถทำงานที่อาจต้องใช้เมื่อมีการเปลี่ยนแปลงชื่อเรื่องเช่นเค้าโครงและตัวแบ่งบรรทัด .
Charles Harley

3

คุณควรใช้การแทนที่ onPrepareOptionsMenu

menu.Clear ();
   if (TabActual == TabSelec.Anuncio)
   {
       menu.Add(10, 11, 0, "Crear anuncio");
       menu.Add(10, 12, 1, "Modificar anuncio");
       menu.Add(10, 13, 2, "Eliminar anuncio");
       menu.Add(10, 14, 3, "Actualizar");
   }
   if (TabActual == TabSelec.Fotos)
   {
       menu.Add(20, 21, 0, "Subir foto");
       menu.Add(20, 22, 1, "Actualizar");
   }
   if (TabActual == TabSelec.Comentarios)
   {
       menu.Add(30, 31, 0, "Actualizar");
   }

นี่คือตัวอย่าง


แน่นอนใช้วิธีการที่ตั้งใจไว้ :) หากคุณตัดสินใจที่จะอ้างอิงถึงเมนูในท้องถิ่นคุณจะต้องกังวลเกี่ยวกับการรั่วของบริบทที่ฉันคิด หรืออาจจะไม่ แต่ไม่แน่นอนด้วยวิธีนี้
William T. Mallard

3

ฉันใช้รหัสนี้เพื่อคำนวณรายการนำทางด้านล่างของฉัน

BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");

2

ประกาศฟิลด์เมนูของคุณ

private Menu menu;

ต่อไปนี้เป็นวิธี onCreateOptionsMenu ()

public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
    try {
        getMenuInflater().inflate(R.menu.menu_main,menu);
    } catch (Exception e) {
        e.printStackTrace();
        Log.i(TAG, "onCreateOptionsMenu: error: "+e.getMessage());
    }
    return super.onCreateOptionsMenu(menu);
}

ต่อไปนี้จะเป็นกิจกรรมตัวตั้งชื่อของคุณ สามารถคลิกหรือผ่านรหัสตามเงื่อนไข

public void setMenuName(){
menu.findItem(R.id.menuItemId).setTitle(/*Set your desired menu title here*/);
}

สิ่งนี้ใช้ได้สำหรับฉัน


0

ดูเหมือนว่าคุณต้องการเปลี่ยนเนื้อหาของเมนูภายในเมธอดโลคอลและเมธอดนี้ถูกเรียกเมื่อใดก็ได้เมื่อใดก็ตามที่มีเหตุการณ์เกิดขึ้นหรือในเธรด UI กิจกรรม

ทำไมคุณไม่ใช้อินสแตนซ์ของเมนูในตัวแปรส่วนกลางใน onPrepareOptionsMenu เมื่อสิ่งนี้ถูกแทนที่และใช้ในวิธีการของคุณ ต้องแน่ใจว่าวิธีการนี้เรียกว่าเมื่อใดก็ตามที่มีเหตุการณ์เกิดขึ้น (เช่นการคลิกปุ่ม) หรือในเธรด UI กิจกรรมตัวจัดการหรือ async-task post-execute

คุณควรรู้ล่วงหน้าเกี่ยวกับดัชนีของรายการเมนูนี้ที่คุณต้องการเปลี่ยน หลังจากล้างเมนูแล้วคุณจะต้องขยาย XML เมนูและอัปเดตชื่อหรือไอคอนของรายการ


0

สำหรับคนที่ต้องการตั้งชื่อแบบคงที่ สิ่งนี้สามารถทำได้ใน AndroidManifest.xml

<activity
    android:name=".ActivityName"
    android:label="Title Text" >
</activity>

ตัวเลือกเมนูข้อความชื่อเรื่อง


3
คำถามสำหรับแบบไดนามิกไม่ใช่แบบคงที่!
EngineSense

ยังคงปรากฏขึ้นในการค้นหาของ Google และช่วยฉันขอบคุณสำหรับการโพสต์
bruchowski

0

ฉันต้องการเปลี่ยนไอคอนเมนูสำหรับแฟรกเมนต์ ฉันเปลี่ยนคำตอบของชาร์ลส์สำหรับคำถามนี้นิดหน่อย

    private Menu top_menu;

    //...
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       setHasOptionsMenu(true);
       //...
       rootview = inflater.inflate(R.layout.first_content,null);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.fragment_menu, menu);
        this.top_menu = menu;
    }


    // my procedure
    private void updateIconMenu() {
         if(top_menu!= null) {
             MenuItem nav_undo = top_menu.findItem(R.id.action_undo);
             nav_undo.setIcon( R.drawable.back);
         }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.