Android:ボタンクリックでオプションメニュー項目を有効/無効にする方法は?


127

onCreateOptionsMenuまたはonOptionsItemSelectedメソッドを使用しているときに簡単に実行できます。

しかし、画面のどこかにボタンがあり、そのボタンをクリックすると、コンテキストメニュー項目が有効/無効になります。

回答:


272

とにかく、ドキュメントはすべてのものをカバーしています。

実行時にメニュー項目を変更する

アクティビティが作成されると、 onCreateOptionsMenu()メソッドは上記のように1回だけ呼び出されます。システムは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()このメニューを押すとどうなるかは変わりますが、見た目は変わりません(何が問題なのですか、Android開発者ですか?)。したがって、無効にてタイトル変更するか、できれば単に非表示にするだけの方が明確MenuItemです。
ヴラド

19
ヒント:falseメニューを完全に無効にするために戻ります。
Bart Friederichs

5
さらに、onPrepareOptionsMenuに関するAPIコメントは明確に述べています:派生クラスは常に(!)基本クラスの実装を呼び出す必要があります。そこでのスーパーコールを忘れました。
AgentKnopf 2013年


実行時に追加されたMenuItemの整数IDをどのようにして知るのですか?名前でのみ追加できます。
Antonio Sesto 2015

66

すべてのAndroidバージョンで、最も簡単な方法:これを使用して、メニューアクションアイコンを無効として表示し、機能を無効としても機能させます。

@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 2014

8
私は0に、しかし130にアルファを設定していないよ
フランク

8
ボタンのコンテキストによって異なります。ボタンが通常提供する機能が現在の状態で完全に使用できない場合、はい、可視性は非表示/なくなっているはずです。ただし、ボタンが通常機能する機能である場合は、何らかの理由(たとえば、ユーザーがプレミアムメンバーになった場合、ユーザーがサインインした場合、ユーザーがインターネットに接続した場合など)を使用して使用できます。灰色になっていると便利です。これにより、何らかの理由でアクセスできない既存の機能があることがユーザーに通知されます。
yiati 2014年

6
アイコンを非表示に設定することは、ほとんどすべてのユースケースでより良いわけではありません。あなたがグループを持っている場合、彼らがその位置に留まり、灰色になっている場合は、特定のプログラム状態で有効にできるオプションがあることをユーザーに示します。物を見えなくして見えなくし、おそらくレイアウトの変更を引き起こすことは非常にばかげています。モードによっては、ほとんどのメニューが灰色で表示され、削除されない理由があります。
RichieHH 2014

1
メニューにアイコンが含まれていない場合はどうなりますか?setAlpha()はできません。
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);
}    

これは、すべてのAndroidバージョンに対する正しい応答です。検証済みの応答は、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() 1回だけ呼び出されます。開始時に状態を設定したため、すべてのアイテムが失われます。

次に、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
  @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

                case R.id.item_id:

                       //Your Code....

                        item.setEnabled(false);
                        break;
              }
            return super.onOptionsItemSelected(item);
     }

口コミから:こんにちは。ソースコードだけで答えないでください。ソリューションがどのように機能するかについて、わかりやすい説明を提供してください。参照:良い回答を書くにはどうすればよいですか?。おかげで
sɐunıɔןɐqɐp

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 '26年

私の答えは完成しました。このコードは機能し、プロジェクトで使用しました
Eric

1
作業に感謝しますが、onCreateContextMenuメソッドで変更できると既に述べた質問を適切に読む必要があります。しかし、私はこのメソッドから外部のコンテキストメニューにアクセスしたいと考えています。
Vikas

onCreateContextMenu一度だけ呼び出されますが、ボタンをクリックしてメニュー項目を有効/無効にすることができます。
Vikas '26年

はい。ただし、コンテキストメニューは通常、非表示になっています。「どこか」ボタンを押して、先ほど述べたようにフラグを設定すると、このコンテキストメニューは表示されなくなり、次回コンテキストメニューを再ロードしたときに、このオプションは非表示になります。別のオプションは、同じ外観の別の種類のメニューを実行して、別のメソッドでイベントを処理することです。
Eric
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.