web-dev-qa-db-ja.com

onPrepareOptionsMenuがメニューエントリを切り替えたときにActionBarを更新するにはどうすればよいですか?

私のアプリでは、メニューエントリを有効/無効にし、onPrepareOptionsMenuから表示できるようにします。

今日、Android:showAsActionメニュー属性を一部のAndroid 2.xアプリに追加して、ActionBarで最も使用されるメニューエントリを表示し始めました。

ActionBarは、有効化/無効化と可視性をすぐには反映しません。この変更を確認するには、右側のメニュードロップダウンをクリックする必要があります。

OK、メニューがonPrepareOptionsMenuを起動することを理解しています。しかし、ActionBarを更新するには何をする必要がありますか?この変更はonOptionsItemSelected内から適用する必要があると思いますが、何を呼ぶべきかわかりません。

メニューは次のとおりです。

<item
    Android:icon="@drawable/ic_menu_mapmode"
    Android:id="@+id/men_mapview"
    Android:showAsAction="ifRoom|withText"
    Android:title="@string/txt_mapview" />

<item
    Android:icon="@drawable/ic_menu_mapmode"
    Android:id="@+id/men_satelliteview"
    Android:showAsAction="ifRoom|withText"
    Android:title="@string/txt_satelliteview" />

OnPrepareOptionsMenuは次のとおりです。

@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
    MenuItem menuItemMapView = menu.findItem(R.id.men_mapview);
    MenuItem menuItemSatelliteView = menu.findItem(R.id.men_satelliteview);

    if (mapView.isSatellite()) {
        menuItemMapView.setEnabled(true).setVisible(true);
        menuItemmenuItemSatelliteView.setEnabled(false).setVisible(false);
    } else {
        menuItemMapView.setEnabled(false).setVisible(false);
        menuItemmenuItemSatelliteView.setEnabled(true).setVisible(true);
    }

    return super.onPrepareOptionsMenu(menu);
}

これがonOptionsItemSelectedです

@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
    switch (menuItem.getItemId()) {
        case R.id.men_mapview:
            mapView.setSatellite(false);
            mapView.setStreetView(true);
            mapView.invalidate();

            invalidateOptionsMenu(); // This works on Android 3.x devices only
            return true;
        case R.id.men_satelliteview:
            mapView.setSatellite(true);
            mapView.setStreetView(false);
            mapView.invalidate();

            invalidateOptionsMenu(); // This works on Android 3.x devices only
            return true;
    }

    return super.onOptionsItemSelected(menuItem);
}

編集: invalidateOptionsMenuを追加すると、これはAndroid 3.xアプリで動作しますが、Android 2.xデバイスが原因でクラッシュします方法がありません。正しい方法は何ですか?

59
Harald Wilhelm

私の選択方法は、ヘルパークラスを作成することです。例えば:

_class VersionHelper
{
    static void refreshActionBarMenu(Activity activity)
    {
        activity.invalidateOptionsMenu();
    }
}
_

上記のコードで、invalidateOptionsMenu();を次のように置き換えます。

_if (Build.VERSION.SDK_INT >= 11)
{
    VersionHelper.refreshActionBarMenu(this);
}
_

この方法の功績はCommonsWareにあります(HoneycombHelperを検索し、彼の本をチェックしてください-強くお勧めします)

83
wirbly

受け入れられた答えに感謝します。 ActionBarActivityを使用しています。このクラスでは、使用できます

supportInvalidateOptionsMenu();
66

つかいます

ActivityCompat.invalidateOptionsMenu(Activity activity)

互換性ライブラリ から。

参照: https://stackoverflow.com/a/14748687/435855

14
Urizev

メニューへの参照を保存して呼び出します:

this.menu.clear();
this.onCreateOptionsMenu(this.menu);
11
Klaasvaak

上記の「Klaasvaak」の回答に基づいています。私はそのサブメニューを使用しています。これは私のために働く:

// Declare and save the menu as global, so it can be called anywhere.
Menu absTopSubMenus;

public boolean onCreateOptionsMenu(Menu menu) {

absTopSubMenus = menu;  // Used for re-drawing this menu anywhere in the codes.

// The remainder of your code below
}

次に、これを再描画するには、単に呼び出します:

// Redraw the top sub-menu
absTopSubMenus.clear();
onCreateOptionsMenu(absTopSubMenus);
4
Britc

サポートライブラリでActionbarActivityのsupportInvalidateOptionsMenu()メソッドを使用できるようになりました。そのため、SDKのバージョンを確認する必要はありません。 API 7以降まで行きます。

http://developer.Android.com/reference/Android/support/v7/app/ActionBarActivity.html

そのためには、これを使用してサポートライブラリのv7をインポートする必要があります

http://developer.Android.com/tools/support-library/setup.html

4
Farfelufrank

getActivity()。invalidateOptionsMenu();

仕事を終わらせます。

3
Karun Shrestha

既にそれを見たことがあるかどうかはわかりませんが、アクションバーを広範囲に使用し、下位API(> 8)のサポートを計画している場合は、actionBarSherlockライブラリをご覧ください。これにより、下位および上位APIのactionBarコードをセクション化する必要がなくなり、次を実行できます。

runOnUiThread(new Runnable(){
  @Override
  public void run(){
    supportInvalidateOptionsMenu();
  }
});
3
user1528493

ここへの道を示してくれた@Klaasvaakに感謝します。 APIレベル11の前後で機能する次のものを使用します。

private void invalidOptionsMenuHelper() {
    if (Build.VERSION.SDK_INT >= 11) {
        invalidateOptionsMenu();

    } else if (mOptionsMenu != null) {
        mOptionsMenu.clear();
        onCreateOptionsMenu(mOptionsMenu);
    }
}

もちろん、メニュー(この場合はmOptionsMenu)への参照を保存する必要があります。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    mOptionsMenu = menu;

    //... create and manage the menu normally
}
2
Mike Repass

また、電話していないことを確認してください

myAppCompatActivity.setToolbarTitle("some dynamic title");

メニューを更新した直後。

描画するスペースがあったとしても、ドロウアブルが表示されないという問題がありました。向きを変更すると、ドローアブルが表示されます。

要約すれば:

主な活動:

public class MainActivity extends AppCompatActivity {

    private boolean showMenu = true;

    public void setShowMenu(boolean show) {
        showMenu = show;
        supportInvalidateOptionsMenu();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.my_menu, menu);
        menu.findItem(R.id.menu_share).setVisible(showMenu);
        // menu.findItem(...
        return true;
    }
}

FragmentNoMenu:

public abstract class FragmentNoMenu extends Fragment {

    protected MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        mainActivity = (MainActivity) getActivity();
        if (mainActivity != null) {
            mainActivity.setShowMenu(false);
        }
    }

}

FragmentWithMenu:

public abstract class FragmentWithMenu extends Fragment {

    protected MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        mainActivity = (MainActivity) getActivity();
        if (mainActivity != null) {
            mainActivity.setShowMenu(true);
        }
    }

}
0
IHeartAndroid