Cách thay đổi văn bản mục menu một cách linh hoạt trong Android


212

Tôi đang cố gắng thay đổi tiêu đề của một mục menu từ bên ngoài onOptionsItemSelected(MenuItem item)phương thức.

Tôi đã làm như sau;

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

tuy nhiên tôi muốn có thể sửa đổi tiêu đề của một mục menu cụ thể bên ngoài phương thức này.


stackoverflow.com/a/32072318/1651286 sẽ là câu trả lời được chấp nhận
Akhil Dad

Câu trả lời:


127

Như JxDarkAngel đã đề xuất, gọi nó từ bất cứ đâu trong Hoạt động của bạn ,

invalidateOptionsMenu();

và sau đó ghi đè:

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

là một lựa chọn tốt hơn nhiều. Tôi đã sử dụng câu trả lời từ https://stackoverflow.com/a/17496503/568197


Giải pháp tốt nhất. Bởi vì cái này ghi đè lên phương thức android thay vì phát minh lại bánh xe.
Azlan Jamal

Chỉ cần lưu ý rằng onPrepareOptionsMenu()được gọi là khá thường xuyên bởi khung Android, ví dụ như khi hiển thị một Hoạt động và mỗi khi menu được hiển thị. Vì vậy, điều này có thể không hiệu quả lắm, nếu thực đơn của bạn không thay đổi thường xuyên.
Mr-IDE

1
invalidateOptionsMenu()cũng sẽ gọi onCreateOptionsMenu(), vì vậy bạn có thể đưa logic cập nhật vào onCreateOptionsMenu().
Mr-IDE

Nếu bạn chỉnh sửa câu này để phù hợp với câu hỏi, tôi sẽ đánh dấu nó là câu trả lời được chấp nhận
Garbit

@Garbit được cập nhật để sử dụng mã của bạn từ câu hỏi ban đầu!
Todd DeLand

375

Tôi sẽ đề nghị giữ một tham chiếu trong hoạt động cho đối tượng Menu bạn nhận được trong onCreateOptionsMothy và sau đó sử dụng tham chiếu đó để lấy MenuItem yêu cầu thay đổi khi và khi bạn cần. Ví dụ: bạn có thể làm một cái gì đó theo các dòng sau:

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

}

Ngoài ra, bạn có thể ghi đè onPrepareOptionsMothy để cập nhật các mục menu mỗi khi menu được hiển thị.


1
Tôi luôn mong đợi Android sẽ có một giải pháp thanh lịch hơn cho những vấn đề này. Có vẻ như câu trả lời đơn giản nhất thường là tốt nhất - cảm ơn.
Steven Wolfe

12

bạn có thể làm điều này để tạo một đối tượng "Menu" toàn cầu, sau đó gán nó trong onCreateOptionMothy

public class ExampleActivity extends AppCompatActivity
    Menu menu;

sau đó chỉ định ở đây

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

Sau đó, sử dụng đối tượng Menu được chỉ định để nhận các mục yêu cầu

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

5

Tạo một phương thức setOptionsTitle () và đặt một trường trong lớp của bạn. Nhu la:

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

...

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

}

Bây giờ khi menu được điền, hãy thay đổi tiêu đề thành trạng thái của bạn:

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

        menu.add(bedStatus);


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

Tôi cần có khả năng thiết lập nó sau khi hoạt động được kết xuất. Vì vậy, không nằm trong hai phương thức đó
Garbit

Gọi setOptionsTitle tại bất kỳ thời điểm nào sau khi hoạt động của bạn được kết xuất. Tôi đoán tôi không hiểu bạn muốn gì vì "Tôi cần có thể thiết lập nó sau khi hoạt động được kết xuất" có nghĩa là với tôi sau khi bạn gọi setContent (R.layout.id), bạn có thể cần thay đổi tùy chọn nào menu hiển thị (mà bạn có thể làm với setOptionsTitle () - từ mọi phương thức, mọi nơi, mọi lúc).
Jack

Mặc dù cách tiếp cận này không hiệu quả nhưng đối tượng Menu quản lý menu sẽ không biết khi nào tiêu đề thay đổi và do đó không thể thực hiện các tác vụ cần thiết khi tiêu đề thay đổi, ví dụ như bố cục và ngắt dòng .
Charles Harley

3

Bạn nên sử dụng ghi đè onPrepareOptionsMothy

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

Dưới đây là một ví dụ


Thật vậy, sử dụng phương pháp dự định. :) Nếu bạn quyết định giữ một tài liệu tham khảo địa phương cho menu, bạn sẽ cần phải lo lắng về rò rỉ bối cảnh tôi sẽ nghĩ. Hoặc có thể không. Nhưng chắc chắn không phải với phương pháp này.
William T. Mallard

3

Tôi sử dụng mã này để trang phục mục điều hướng dưới cùng của mình

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

2

Khai báo trường menu của bạn.

private Menu menu;

Sau đây là phương thức onCreateOptionsMothy ()

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

Sau đây sẽ là hoạt động setter tên của bạn. Thông qua một lần bấm nút hoặc thông qua mã có điều kiện

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

Điều này làm việc cho tôi.


0

Dường như với tôi rằng bạn muốn thay đổi nội dung của menu bên trong một phương thức cục bộ và phương thức này được gọi bất cứ lúc nào, bất cứ khi nào xảy ra sự kiện hoặc trong luồng UI hoạt động.

Tại sao bạn không lấy ví dụ của Menu trong biến toàn cục trong onPrepareOptionsMothy khi điều này bị ghi đè và sử dụng trong phương thức này của bạn. Hãy chắc chắn rằng phương thức này được gọi bất cứ khi nào một sự kiện xảy ra (như nhấp vào nút) hoặc trong luồng UI hoạt động, trình xử lý hoặc tác vụ sau khi thực thi tác vụ.

Bạn nên biết trước chỉ mục của mục menu này bạn muốn thay đổi. Sau khi xóa menu, bạn cần làm tăng menu XML và cập nhật tên hoặc biểu tượng của mặt hàng của bạn.


0

Đối với những người cần tiêu đề được đặt tĩnh. Điều này có thể được thực hiện trong AndroidManifest.xml

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

Tùy chọn Menu Tiêu đề Văn bản


3
Câu hỏi là dành cho năng động, không tĩnh!
EngineSense

vẫn tìm kiếm trên google và giúp tôi, cảm ơn vì đã đăng bài
bruchowski

0

Tôi cần phải thay đổi biểu tượng menu cho đoạn. Tôi đã thay đổi câu trả lời của Charles cho câu hỏi này một chút cho đoạn:

    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);
         }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.