Меню настроек Android во фрагменте - PullRequest
370 голосов
/ 29 ноября 2011

Я пытаюсь добавить элемент в меню параметров из группы фрагментов.

Я создал новый класс MenuFragment и расширил его для фрагментов, в которые я хочу включить элемент меню.Вот код:

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);
    }
}

По какой-то причине onCreateOptionsMenu не работает.

Ответы [ 19 ]

569 голосов
/ 29 ноября 2011

Вызовите метод super:

@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);
}

Поместите операторы журнала в код, чтобы увидеть, не вызывается ли метод или меню не изменяется вашим кодом.

Также убедитесь, что вы звоните setHasOptionsMenu(boolean) в onCreate(Bundle), чтобы уведомить фрагмент о том, что он должен участвовать в обработке меню опций.

188 голосов
/ 19 августа 2013

У меня была та же проблема, но я думаю, что лучше подвести итог и представить последний шаг, чтобы она заработала:

  1. Добавьте метод setHasOptionsMenu (true) в ваш фрагмент onCreate(Bundle savedInstanceState)method.

  2. Override onCreateOptionsMenu(Menu menu, MenuInflater inflater) (если вы хотите сделать что-то другое в меню вашего фрагмента) и onOptionsItemSelected(MenuItem item) методы в вашем фрагменте.

  3. Внутри onOptionsItemSelected(MenuItem item) метода Activity, убедитесь, что вы возвращаете false, когда действие элемента меню будет реализовано в onOptionsItemSelected(MenuItem item) методе Fragment.

Пример:

Активность

@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;
}
153 голосов
/ 03 октября 2012

Если вы обнаружите, что метод onCreateOptionsMenu(Menu menu, MenuInflater inflater) не вызывается, убедитесь, что вы вызываете следующее из метода onCreate(Bundle savedInstanceState) фрагмента:

setHasOptionsMenu(true)
50 голосов
/ 05 ноября 2014

Если вам нужно menu для обновления webview внутри определенного Fragment, вы можете использовать:

Фрагмент

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>
23 голосов
/ 04 марта 2015

В 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);
}

Вам не нужно переопределять onCreateOptionsMenu в вашем классе Fragment снова. Пункты меню можно изменить (добавить / удалить), переопределив метод onPrepareOptionsMenu, доступный во фрагменте.

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

}
16 голосов
/ 26 марта 2015

Вам нужно использовать 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);
    }
14 голосов
/ 22 июня 2018

TL; DR

Используйте android.support.v7.widget.Toolbar и просто выполните:

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

Автономная панель инструментов

Большинство предлагаемых решений, таких как setHasOptionsMenu(true), работают толькокогда родительская активность имеет панель инструментов в своем макете и объявляет ее через setSupportActionBar().Затем фрагменты могут участвовать в заполнении меню этого точного ActionBar :

Fragment.onCreateOptionsMenu (): инициализировать содержимое меню стандартных параметров хоста фрагмента.1019 *

Если вам нужна отдельная панель инструментов и меню для одного конкретного фрагмента , вы можете сделать следующее:

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).

9 голосов
/ 07 февраля 2018

В моем случае вот шаги.

Шаг-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);
}
7 голосов
/ 23 июня 2016

Если вы хотите добавить свое меню в пользовательский

@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);
}
7 голосов
/ 26 июля 2013

У меня была такая же проблема, мои фрагменты были страницами ViewPager.Причина, по которой это происходило, заключается в том, что при создании экземпляра FragmentPagerAdapter я использовал дочерний диспетчер фрагментов, а не диспетчер фрагментов поддержки активности.

...