Androidでフラグメントにオプションメニューを追加する方法


399

フラグメントのグループからオプションメニューにアイテムを追加しようとしています。

新しいを作成しました MenuFragmentクラスを、メニュー項目を含めたいフラグメントのためにこれを拡張しました。コードは次のとおりです。

Java:

public class MenuFragment extends Fragment {

    MenuItem fav;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

コトリン:

class MenuFragment : Fragment {

    lateinit var fav: MenuItem

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

なんらかの理由でonCreateOptionsMenu実行されないようです。


ばかげた質問かもしれません...あなたは右のメニューボタンを押しますか?
Ovidiu Latcu

2
..lol ...はい、メニューボタンを押しました。私はそれを使って、または使わずに試してみました。fav.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
ミスターバスマン

こんにちは、多分このスレッドはあなたを助けるでしょう、または実用的な例のためにAPIデモをチェックしてください。
kameny

回答:


605

superメソッドを呼び出します。

Java:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater);
    }

コトリン:

    override fun void onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater)
    }

コードにログステートメントを挿入して、メソッドが呼び出されていないかどうか、またはメニューがコードによって修正されていないかどうかを確認します。

また、フラグメントがオプションメニューの処理に参加する必要があることを通知するために呼び出していることsetHasOptionsMenu(boolean)を確認してくださいonCreate(Bundle)


2
おかげで、私はスーパーメソッドを追加し、@ Overrideを削除したためにこれを追加し直したことに気付き、Eclipseがエラーをスローしたため、MenuInflaterを置き換えてandroid.view.MenuInflaterをインポートしました。android.support.v4.view.MenuInflaterをインポートする代わりに; そして今、すべてが働いています
ミスターバスマン

183
FragmentのonCreateでsetHasOptionsMenu(true)を呼び出さないことで、2倍になりました
joshkendrick

7
アクティビティをフラグメントに転送していて、この問題に遭遇しました。メソッドシグネチャがpublic booleanからpublic voidに変更され、引数も変更されました。これに注意してください!
you786

14
Fragment.onCreateOptionsMenu(Menu、MenuInflater)は空のメソッドであるため、superを呼び出す必要はまったくありません。ここでの唯一の間違いは、間違ったメソッドシグネチャと、おそらくonCreate()のsetHasOptionsMenu()の欠落でした
cmende

6
super.onCreateOptionsMenuをinflater.inflate(R.menu.menu_custom、menu);に置き換えます。
Code_Worm

197

私は同じ問題を抱えていましたが、それを機能させるための最後のステップを要約して紹介する方が良いと思います:

  1. FragmentのonCreate(Bundle savedInstanceState)メソッドにsetHasOptionsMenu(true)メソッドを追加します。

  2. onCreateOptionsMenu(Menu menu, MenuInflater inflater)フラグメントのメニュー(フラグメントのメニューで別のことをしたい場合)とonOptionsItemSelected(MenuItem item)メソッドをオーバーライドします。

  3. onOptionsItemSelected(MenuItem item)アクティビティのメソッド内で、メニュー項目アクションがonOptionsItemSelected(MenuItem item)フラグメントのメソッドに実装される場合は、必ずfalseを返します。

例:

アクティビティ

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Do Activity menu item stuff here
            return true;

        case R.id.fragment_menu_item:

            // Not implemented here
            return false;
        default:
            break;
    }

    return false;
}

断片

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    ....
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Not implemented here
            return false;
        case R.id.fragment_menu_item:

            // Do Fragment menu item stuff here
            return true;

        default:
            break;
    }

    return false;
}

2
ちょうど欠けていたsetHasOptionsMenu(true);おかげで
チャドビンガム2014年

1
一部のデバイスのviewPagerでは、フラグメントに2回アクセスしたときにのみメニューが表示されます
Roel

3
@Marco HCコードは正常に動作します。しかし、アクティビティまたはフラグメントのメニューの一部を非表示にしたい場合はどうなりますか?どのオプションメニューを実装するか(アクティビティとフラグメント内)について言及しました。しかし、メニューを非表示にしたい場合はどうなりますか?
Shreyash Mahajan 2015

@iDroidExplorerは、そのMenuItemへの参照を保持し、可視性を存在しないか不可視に設定します。それはあなたの質問ですか?
マルコHC

@iDroidExplorer私は彼のコードを試してみましたが、方法はわかりませんが、他のフラグメントに切り替えると、メニューが自動的に非表示になります。
Noor Ali Butt

156

あなたが見つけた場合はonCreateOptionsMenu(Menu menu, MenuInflater inflater)メソッドが呼び出されていない、あなたが断片年代から、次を呼び出す作るonCreate(Bundle savedInstanceState)方法:

setHasOptionsMenu(true)

NullPointerExceptionのようなエラーが発生する
Pratik Butani 2013年

2
いい視点ね。静的newInstanceメソッドからsetHasOptionMenuメソッドを呼び出していました。savedInstanceStateがnullの場合にのみフラグメントをアタッチしていたため、画面構成が変更されたときにメニューが作成されませんでした。フラグメントのonCreateメソッドは、setHasOptionMenuをtrueに設定する正しい場所です。
argenkiwi 2013

1
私はを使用してToolbarおり、それを実行setHasOptionsMenu(true)するonCreateView()代わりonCreate()に呼び出す必要がありました。
CLOUGH

60

特定のの内部menuを更新する必要がある場合は、次を使用できます。webviewFragment

フラグメント

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // TODO Add your menu entries here
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.exit:
        System.exit(1);
        break;

    case R.id.refresh:
        webView.reload();
        break;
    }
    return true;

}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/exit" android:title="Exit" android:icon="@drawable/ic_action_cancel" />
    <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_action_refresh" />
</menu>

31

TL; DR

を使用してandroid.support.v7.widget.Toolbar、次のようにします。

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

スタンドアロンツールバー

以下のような提案ソリューションのほとんどのsetHasOptionsMenu(true)場合にのみ働いている親の活動がそのレイアウトでツールバーを持っているし、それを経由して宣言しますsetSupportActionBar()。次に、Fragmentsはこの正確なActionBarのメニュー入力に参加できます。

Fragment.onCreateOptionsMenu():Fragmentホストの標準オプションメニューのコンテンツを初期化します。

特定のフラグメントのスタンドアロンツールバーとメニューが必要な場合は、以下を実行できます。

menu_custom_fragment.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

CustomFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

はい、それはとても簡単です。onCreate()またはをオーバーライドする必要さえありませんonCreateOptionsMenu()

PS:これはandroid.support.v4.app.Fragmentおよびでのみ機能しandroid.support.v7.widget.Toolbarます(またAppCompatActivity、でAppCompatテーマを使用してくださいstyles.xml)。


1
本当に私を助けてくれました
ブラフミーadigopula

23

では、menu.xmlすべてのメニュー項目を追加する必要があります。その後、初期ロードで表示したくないアイテムを非表示にすることができます。

menu.xml

<item
    android:id="@+id/action_newItem"
    android:icon="@drawable/action_newItem"
    android:showAsAction="never"
    android:visible="false"
    android:title="@string/action_newItem"/>

setHasOptionsMenu(true)onCreate()メソッドを追加して、Fragmentクラスのメニュー項目を呼び出します。

FragmentClass.java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

onCreateOptionsMenuFragmentクラスで再度オーバーライドする必要はありません。onPrepareOptionsMenuFragmentで使用可能なメソッドをオーバーライドすることにより、メニュー項目を変更(追加/削除)できます。

@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_newItem).setVisible(true);
    super.onPrepareOptionsMenu(menu);

}

16

メニューを拡張する前に、menu.clear()を使用する必要があります。

@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.menu, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

そして

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

1
これは、異なるフラグメントに異なるメニューが必要で、フラグメントを置き換えるのではなく追加する場合に適切です。
Akshay Mahajan 2017

ありがとうございました!menu.clear()は、アクティビティのメニューオプションを削除するのに役立ちます。
kimcy929

13

私の場合、ここに手順があります。

ステップ1

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Here notify the fragment that it should participate in options menu handling.
    setHasOptionsMenu(true);
}

ステップ2

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // First clear current all the menu items
    menu.clear();

    // Add the new menu items
    inflater.inflate(R.menu.post_stuff, menu);

    super.onCreateOptionsMenu(menu, inflater);
}

ステップ-3

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.post_stuff:
            Log.d(TAG, "Will post the photo to server");
            return true;
        case R.id.cancel_post:
            Log.d(TAG, "Will cancel post the photo");
            return true;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}

menu.clear()クリアされた前のメニューを使用して、メインアクティビティのメニューはすでにありました。私のために働いた:)
アンブセルヴァンロッキー

8

メニューカスタムを追加したい場合

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_custom, menu);
}

タブビューがあり、フラグメントごとに異なるメニューを膨らませたい場合はどうなりますか?
Jainam Jhaveri 2017

7

私は同じ問題を抱えていました、私のフラグメントはViewPagerのページでした。それが起こっていた理由は、FragmentPagerAdapterをインスタンス化するときに、アクティビティサポートフラグメントマネージャーではなく子フラグメントマネージャーを使用していたためです。


3

メニューファイル:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/play"
        android:titleCondensed="Speak"
        android:showAsAction="always"
        android:title="Speak"
        android:icon="@drawable/ic_play">
    </item>
    <item
        android:id="@+id/pause"
        android:titleCondensed="Stop"
        android:title="Stop"
        android:showAsAction="always"
        android:icon="@drawable/ic_pause">
    </item>
</menu>

活動コード:

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            Toast.makeText(getApplicationContext(), "speaking....", Toast.LENGTH_LONG).show();
            return false;

        case R.id.pause:
            Toast.makeText(getApplicationContext(), "stopping....", Toast.LENGTH_LONG).show();
            return false;

        default:
            break;
    }

    return false;
}

フラグメントコード:

@Override

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            text = page.getText().toString();
            speakOut(text);

            // Do Activity menu item stuff here
            return true;

        case R.id.pause:
            speakOf();

            // Not implemented here
            return true;

        default:
            break;
    }
    return false;
}

3

あなたのコードは大丈夫です。メソッドに欠けているのはスーパーだけです:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO add your menu : 
    inflater.inflate(R.menu.my_menu, menu);
    //TODO call super
    super.onCreateOptionsMenu(menu, inflater);
}

2

ここでの答えがどれもうまくいかなかったので、私は頭がおかしくなりました。

私が呼び出さなければならないメニューを表示するには: setSupportActionBar(toolbar)

できた!

注:toolbarビューが同じアクティビティレイアウトにない場合、上記の呼び出しをアクティビティクラスから直接使用することはできません。この場合、フラグメントクラスからそのアクティビティを取得してを呼び出す必要がありますsetSupportActionBar(toolbar)。覚えておいてください:アクティビティクラスはAppCompatActivityを拡張する必要があります。

この回答がお役に立てば幸いです。


1

フラグメントビューの作成後にオプションメニューを設定すると、うまくいきました。

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);        
}

1

私の問題は少し異なりました。私はすべてを正しく行いました。しかし、私はフラグメントをホストするアクティビティの間違ったクラスを継承していました。

明確にonCreateOptionsMenu(Menu menu, MenuInflater inflater)するために、フラグメントでオーバーライドしている場合は、このフラグメントをホストするアクティビティクラスが継承していることを確認してくださいandroid.support.v7.app.ActionBarActivity(APIレベル11未満をサポートする場合)。

android.support.v4.app.FragmentActivity11未満のAPIレベルをサポートするためにを継承していました。


1

私がこれに追加することと、それが私にとってうまくいかなかった理由。

それはナップスターの答えに似ています。

  1. あなたのフラグメントのホスティング活動が延びていることを確認しAppCompatActivity、ありませんFragmentActivity

    public class MainActivity extends AppCompatActivity {
    
    }

    FragmentActivityのGoogleリファレンスドキュメントから:

    注:アクションバーを含むアクティビティを実装する場合は、代わりに、このクラスのサブクラスであるActionBarActivityクラスを使用する必要があります。これにより、APIレベル7以上でフラグメントAPIを使用できます。

  2. Napsterの回答を更新するには- ActionBarActivity廃止予定のため、AppCompatActivity代わりにを使用してください。

  3. を使用する場合はAppCompatActivity、「アクティビティテーマTheme.AppCompatまたは類似のテーマ」(Googleドキュメント)も設定してください。

注:android.support.v7.app.AppCompatActivityandroid.support.v4.app.FragmentActivityクラスのサブクラスです(AppCompatActivity ref docを参照)。


1

メニューフォルダに.menu xmlファイルを作成し、このxmlを追加します

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_menu_search"
    android:title="@string/action_search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always|collapseActionView" />

あなたのフラグメントクラスでこのメソッドをオーバーライドし、

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

次に、フラグメントクラスにメニューXMLファイルを設定します

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_main, menu);

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView)    
    MenuItemCompat.getActionView(item);


    MenuItemCompat.setOnActionExpandListener(item,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Do something when collapsed

                    return true; // Return true to collapse action view
                }

                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Do something when expanded
                    return true; // Return true to expand action view
                }
            });

}

0

上記のすべてが機能しない場合は、デバッグして、関数onCreateOptionsMenuが呼び出されたことを確認する必要があります(デバッグまたはログの書き込み...)

実行されない場合は、Androidテーマがアクションバーをサポートしていない可能性があります。 AndroidManifest.xmlを開きandroid:theme、テーマサポートアクションバーの値を設定します

 <activity
     android:name=".MainActivity"
     android:label="@string/app_name"
     android:theme="@style/Theme.AppCompat">

0

onCreateメソッドにsetHasOptionMenu()を追加します

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

次に、onCreateOptionsMenuをオーバーライドします

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.add("Menu item")
            .setIcon(android.R.drawable.ic_delete)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.