ActionBar에 표시된 메뉴 항목을 업데이트하는 방법은 무엇입니까?


93

2 개의 조각이있는 활동이 있습니다. 둘 다 ListFragments이며 둘 다 Menu에 MenuItems를 제공합니다. ActionBar에 버튼으로 표시되도록 android : showAsAction 속성을 설정 한 MenuItem이 하나 있습니다. 잘 작동합니다.

이제 MenuItem은 상태에 따라 다릅니다. 대기열을 일시 중지하고 다시 시작하기위한 일시 중지 / 다시 시작 메뉴 옵션입니다. 내 문제는 조각이 만들어 질 때 초기 동상을 설정하는 방법을 알아낼 수 없다는 것입니다.

상태는 대기열이 일시 중지되었는지 여부에 따라 다릅니다. 그래서 큐를 가져오고 큐 상태에 따라 부울 (일시 중지됨)을 설정하는 AsyncTask가 있습니다. 큐의 마지막으로 알려진 상태를 기반으로 일시 중지 메뉴 항목의 텍스트를 설정하기 위해 onPrepareOptionsMenu를 호출하고 있으며 실제 메뉴에 MenuItem을두면 잘 작동합니다. 메뉴 아이콘을 탭하면 onPrepareOptionsMenu가 실행되고 메뉴가 표시되기 전에 업데이트됩니다.

문제는 동일한 MenuItem을 ActionBar (showAsAction)에두면 어떻게 onPrepareOptionsMenu를 호출하지 않고 강제로 업데이트 할 수 있습니까? 앱을 처음 시작할 때 대기열을 가져 오기 위해 요청을 보내지 만 ActionBar가 설정되고 표시되면 작업이 반환되기 때문에이 작업을 수행 할 수 있어야합니다. 큐 업데이트를받을 때마다 호출되는 내 프래그먼트에 핸들러를 만들었지 만 거기에서 ActionBar의 MenuItem 텍스트를 어떻게 업데이트 할 수 있습니까? onPrepareOptionMenu를 제외하고는 현재 설정된 메뉴를 조작하여 조작하는 방법을 찾을 수없는 것 같습니다.

롭 W.

답변:


174

옵션 # 1 : invalidateOptionsMenu(). 이것이 액션 바를 즉시 다시 그릴 지 여부를 모르겠습니다.

옵션 # 2 : getActionView()영향을받는 MenuItem. 그것은 가능성이 showAsAction단순히 자동으로 액션 뷰를 작성합니다. 그렇다면 아마도 해당을 활성화 / 비활성화 할 수 있습니다 View.

onPrepareOptionMenu를 제외하고는 현재 설정된 메뉴를 조작하여 조작하는 방법을 찾을 수없는 것 같습니다.

Menu건네 받은 물건에 매달릴 수 있습니다 onCreateOptionsMenu(). 문서 인용 :

다음에 onCreateOptionsMenu ()가 호출 될 때까지 메뉴 (및 여기에서 생성 된 모든 항목)를 안전하게 잡고 원하는대로 수정할 수 있습니다.


2
옵션 # 1을 시도했고 이것이 트릭을 수행했습니다. 별도의 스레드에서 콜백으로 UI를 업데이트하려고했기 때문에 실제로 UI 스레드에 있지 않았기 때문에 예외가 발생했습니다. 이 문제를 해결하기 위해 Handler를 만들고 콜백이 호출 될 때 핸들러에 새로 고침 메시지를 보냈습니다. 그러나 궁극적으로 메뉴를 새로 고치기 위해 getActivity (). invalidateOptionsMenu ()를 사용했습니다.
brockoli 2011

@brockoli : 아, 좋아요! 해당 메소드에 대한 Javadocs의 문구를 감안할 때 원하는 효과를 얻을 수 있을지 의심 스러웠지만 처음에 API 레벨 11에 추가 한 이유 인 것 같았습니다. 그것이 당신을 위해 일하고 있다는 것을 듣고 다행입니다!
CommonsWare 2011

나는 이것을 알아 내려고 벽에 머리를 부딪 쳤고 그것은 매력처럼 작동한다!
MinceMan 2012 년

7
당신이 지원 라이브러리를 사용하는 경우, 사용 supportInvalidateOptionsMenu()대신에
팀 한국 과학 기술 연구원 (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 public boolean onCreateOptionsMenu (Menu menu) {MenuInflater inflater = getMenuInflater (); inflater.inflate (R.menu.magazine_swipe_activity, 메뉴); mnuTopMenuActionBar_ = 메뉴; true를 반환하십시오. }
cV2

그렇게하면 동기화 문제가 발생할 수 있습니다. 내말은. onCreateOptionMenu가 언제 실행 될지 정확히 알지 못하므로 mnuTopMenuActionBar_초기화되지 않은 코드 조각에 도달 할 수 있습니다 . 그 문제를 어떻게 해결 하시겠습니까?
acrespo


11

Fragment에서 메뉴를 새로 고치려면 다음을 호출하십시오.

getActivity().invalidateOptionsMenu();

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

이 화려한이다
스티브 카마 우

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.