안드로이드 : 버튼 클릭시 옵션 메뉴 항목을 활성화 / 비활성화하는 방법은 무엇입니까?


127

내가 사용 onCreateOptionsMenu하거나 onOptionsItemSelected방법을 사용할 때 쉽게 할 수 있습니다 .

그러나 화면 어딘가에 버튼이 있으며 해당 버튼을 클릭하면 상황에 맞는 메뉴 항목을 활성화 / 비활성화해야합니다.

답변:


272

어쨌든 문서 는 모든 것을 다룹니다.

런타임시 메뉴 항목 변경

활동이 작성되면 onCreateOptionsMenu()위에서 설명한대로 메소드가 한 번만 호출됩니다. 시스템 Menu은 활동이 파괴 될 때까지이 방법으로 정의한 것을 유지하고 재사용합니다 . 옵션 메뉴를 처음 만든 후 언제든지 변경하려면 onPrepareOptionsMenu()메서드 를 재정의해야합니다 . 현재 존재하는 Menu 객체를 전달합니다. 응용 프로그램의 현재 상태에 따라 메뉴 항목을 제거, 추가, 비활성화 또는 활성화하려는 경우에 유용합니다.

예 :

@Override
public boolean onPrepareOptionsMenu (Menu menu) {
    if (isFinalized) {
        menu.getItem(1).setEnabled(false);
        // You can also use something like:
        // menu.findItem(R.id.example_foobar).setEnabled(false);
    }
    return true;
}

Android 3.0 이상에서 작업 표시 줄에 메뉴 항목이 표시되면 옵션 메뉴가 항상 열려있는 것으로 간주됩니다. 이벤트가 발생하고 메뉴 업데이트를 수행하려는 invalidateOptionsMenu()경우 시스템 호출을 요청 하려면 호출해야합니다 onPrepareOptionsMenu().


2
setEnable()이 메뉴를 누를 때 발생하는 동작은 변경하지만 모양이 변경되지는 않습니다 (안드로이드 개발자). 따라서 제목을 비활성화 하고 변경하는 것이 더 명확 하거나 MenuItem눈에 보이지 않게 만드는 것이 좋습니다 .
Vlad

19
빠른 팁 : false메뉴를 완전히 비활성화하려면 돌아가십시오 .
Bart Friederichs

5
또한 onPrepareOptionsMenu에 대한 API 주석에는 다음과 같이 명시되어 있습니다. 파생 클래스는 항상 기본 클래스 구현을 (!) 호출해야합니다. 당신은 거기에 당신의 슈퍼 전화를 잊었다.
Agent Knopf


런타임에 추가 된 MenuItem의 정수 ID를 어떻게 알 수 있습니까? 이름으로 만 추가 할 수 있습니다.
Antonio Sesto

66

모든 안드로이드 버전에서 가장 쉬운 방법 : 이것을 사용하여 메뉴 작업 아이콘을 비활성화 된 것으로 표시하고 기능을 비활성화 된 상태로 만듭니다.

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    MenuItem item = menu.findItem(R.id.menu_my_item);

    if (myItemShouldBeEnabled) {
        item.setEnabled(true);
        item.getIcon().setAlpha(255);
    } else {
        // disabled
        item.setEnabled(false);
        item.getIcon().setAlpha(130);
    }
}

1
가시성을 false로 설정할 수 있는데 왜 알파를 0으로 설정합니까?
MLProgrammer-CiM

8
알파를 0으로 설정하지 않고 130으로 설정합니다.
Frank

8
버튼의 상황에 따라 다릅니다. 버튼이 정상적으로 작동하는 기능을 현재 상태에서 완전히 사용할 수 없다면, 가시성이 보이지 않아야합니다. 그러나 어떤 이유로 든 버튼을 정상적으로 사용할 수있는 기능 (예 : 사용자가 프리미엄 회원이 된 경우, 사용자가 로그인 한 경우, 사용자가 인터넷에 연결 한 경우 등)을 사용하면 버튼이 회색으로 표시됩니다. 그런 다음 어떤 이유로 액세스 할 수없는 기존 기능이 있음을 사용자에게 알려주기 때문입니다.
yiati

6
거의 모든 사용 사례에서 아이콘을 보이지 않게 설정하는 것이 좋지 않습니다. 그룹이 더 나은 그룹은 위치에 머무르고 회색으로 표시되어 특정 프로그램 상태에서 활성화 할 수있는 옵션이 있음을 사용자에게 나타냅니다. 보이지 않는 것과 보이지 않는 것을 만들고 레이아웃 변경을 일으키는 것은 매우 어리석은 일입니다. 대부분의 메뉴가 항목을 흐리게 표시하고 모드에 따라 제거하지 않는 이유가 있습니다.
RichieHH

1
메뉴에 아이콘이 없으면 어떻게됩니까? Alpha ()를 설정할 수 없습니다.
Latief Anwar

42

옵션 메뉴를 만들 때 항목을 변수로 저장 한 다음 원하는대로 속성을 변경할 수 있습니다.

private MenuItem securedConnection;
private MenuItem insecuredConnection;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.connect_menu, menu);
    securedConnection = menu.getItem(0);
    insecuredConnection =  menu.getItem(1);
    return true;
}

public void foo(){
       securedConnection.setEnabled(true);
}    

그것은 모든 안드로이드 버전에 대한 올바른 응답입니다. 검증 된 응답은 API 11> 장치에만 유효합니다.
Marco HC

2
나는 이것을 시도했지만 작동하지 않습니다. 당신은 의미 했습니까 onPrepareOptionsMenu?
Christopher Pickslay

6

@Vikas 버전 단순화

@Override
public boolean onPrepareOptionsMenu (Menu menu) {

    menu.findItem(R.id.example_foobar).setEnabled(isFinalized);
    return true;
}

4

AsyncTask가 완료되었을 때 항목을 활성화 또는 비활성화하기 위해 현재 메뉴를 업데이트하는 방법.

내 유스 케이스에서는 AsyncTask가 데이터를로드하는 동안 메뉴를 비활성화해야했고 모든 데이터를로드 한 후 사용자가 사용할 수 있도록 모든 메뉴를 다시 활성화해야했습니다.

이로 인해 데이터가로드되는 동안 사용자가 메뉴 항목을 클릭 할 수 없었습니다.

먼저 상태 변수를 선언하고 변수가 0이면 메뉴가 표시되고 해당 변수가 1이면 메뉴가 숨겨집니다.

private mMenuState = 1; //I initialize it on 1 since I need all elements to be hidden when my activity starts loading.

그런 다음 onCreateOptionsMenu()이 변수를 확인합니다 .1이면 모든 항목을 비활성화합니다. 그렇지 않으면 모두 표시합니다.

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.menu_galeria_pictos, menu);

        if(mMenuState==1){
            for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(false);
            }
        }else{
             for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(true);
            }
        }

        return super.onCreateOptionsMenu(menu);
    }

이제 내 활동이 시작되면 onCreateOptionsMenu() 되면 한 번만 호출되며 항목을 설정했기 때문에 모든 항목이 사라집니다.

그런 다음 AsyncTask를 생성합니다. 여기서 상태 변수를 0으로 설정합니다. onPostExecute()

이 단계는 매우 중요합니다!

전화 할 때 invalidateOptionsMenu(); 하면 다시 시작됩니다onCreateOptionsMenu();

따라서 상태를 0으로 설정 한 후에는 모든 메뉴를 다시 그리지 만 이번에는 변수가 0 인 상태에서 모든 비동기 프로세스가 완료된 후 모든 메뉴가 표시되며 사용자는 메뉴를 사용할 수 있습니다 .

 public class LoadMyGroups extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mMenuState = 1; //you can set here the state of the menu too if you dont want to initialize it at global declaration. 

        }

        @Override
        protected Void doInBackground(Void... voids) {
           //Background work

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            mMenuState=0; //We change the state and relaunch onCreateOptionsMenu
            invalidateOptionsMenu(); //Relaunch onCreateOptionsMenu

        }
    }

결과

여기에 이미지 설명을 입력하십시오


2

내비게이션 드로어에서 수행 할 때 최상의 솔루션

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.setGroupVisible(0,false);
        return true;
    }

이것은 전체 메뉴를 숨기고 다시 열 수 없게합니다
MrStahlfelge

2

오래된 질문에 대한 더 현대적인 답변 :

MainActivity.kt

private var myMenuIconEnabled by Delegates.observable(true) { _, old, new ->
    if (new != old) invalidateOptionsMenu()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    findViewById<Button>(R.id.my_button).setOnClickListener { myMenuIconEnabled = false }
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_main_activity, menu)
    return super.onCreateOptionsMenu(menu)
}

override fun onPrepareOptionsMenu(menu: Menu): Boolean {
    menu.findItem(R.id.action_my_action).isEnabled = myMenuIconEnabled
    return super.onPrepareOptionsMenu(menu)
}

menu_main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/action_my_action"
    android:icon="@drawable/ic_my_icon_24dp"
    app:iconTint="@drawable/menu_item_icon_selector"
    android:title="My title"
    app:showAsAction="always" />
</menu>

menu_item_icon_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?enabledMenuIconColor" android:state_enabled="true" />
<item android:color="?disabledMenuIconColor" />

attrs.xml

<resources>   
    <attr name="enabledMenuIconColor" format="reference|color"/>
    <attr name="disabledMenuIconColor" format="reference|color"/>
</resources>

styles.xml or themes.xml

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="disabledMenuIconColor">@color/white_30_alpha</item>
    <item name="enabledMenuIconColor">@android:color/white</item>

앱 주위에 많은 상용구가 없어도 사용할 수있는 훌륭한 접근 방식입니다.
Arthur

어떤 문제가 있습니까?
ExpensiveBelly

@ExpensiveBelly 그 자체로는 문제가 아니라 공개 공지입니다.
Big McLargeHuge


1

내가 한 것은에 메뉴에 대한 참조를 저장하는 것 onCreateOptionsMenu입니다. 이것은 각 개별 항목을 저장하는 대신 전체 메뉴를 저장했다는 점을 제외하고는 nir의 대답과 비슷합니다.

메뉴 선언 Menu toolbarMenu;.

그런 다음 onCreateOptionsMenu메뉴를 변수 에 저장하십시오.

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

이제 언제든지 메뉴와 모든 항목에 액세스 할 수 있습니다. toolbarMenu.getItem(0).setEnabled(false);


0
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    // getMenuInflater().inflate(R.menu.home, menu);
    return false;
}

2
이 코드는 OP의 질문에 대답 할 수 있지만 몇 가지 설명은 현재 및 미래의 사용자가 귀하의 응답을 더 잘 이해하는 데 도움이됩니다.
Thom

0

메뉴가 보이는 경우

menu.findItem(R.id.id_name).setVisible(true);

메뉴를 숨기는 경우

menu.findItem(R.id.id_name).setVisible(false);

-4

일반적으로 런타임에서 뷰의 속성을 변경할 수 있습니다.

(Button) item = (Button) findViewById(R.id.idBut);

그리고...

item.setVisibility(false)

그러나

ContextMenu에서 옵션의 가시성을 수정하려면 버튼을 누르면 플래그를 활성화 한 다음 onCreateContextMenu에서 다음과 같이 할 수 있습니다.

 @Override
        public void onCreateContextMenu(ContextMenu menu, 
                View v,ContextMenu.ContextMenuInfo menuInfo) {

            super.onCreateContextMenu(menu, v, menuInfo);

                menu.setHeaderTitle(R.string.context_title);

                if (flagIsOn()) {
                    addMenuItem(menu, "Option available", true);
                } else {
                    Toast.makeText(this, "Option not available", 500).show();
                }

        }

이게 도움이 되길 바란다


버튼이 아닌 메뉴 항목을 비활성화하고 싶습니다.
Vikas

내 답변이 완료되었습니다. 이 코드는 작동합니다. 프로젝트에서 사용했습니다
Eric

1
일 해주셔서 감사 합니다만, onCreateContextMenu방법을 바꿀 수 있다고 이미 언급 한 질문을 올바르게 읽어야 합니다. 그러나이 방법에서 컨텍스트 메뉴에 액세스하고 싶습니다.
Vikas

onCreateContextMenu한 번만 호출되지만 버튼을 많이 클릭하면 메뉴 항목을 활성화 / 비활성화 할 수 있습니다.
Vikas

예. 그러나 상황에 맞는 메뉴는 일반적으로 숨겨져 있습니다. '어딘가 버튼'을 누르고 내가 말한대로 플래그를 설정하면 다음 상황에 맞는 메뉴가 표시되지 않고 다음에 상황에 맞는 메뉴를 다시로드하면이 옵션이 보이지 않습니다. 다른 옵션은 다른 방법으로 이벤트를 처리하기 위해 동일한 모양으로 다른 종류의 메뉴를 수행하는 것입니다.
에릭
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.