Меню опций Android во фрагменте

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

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

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 ответов


вызовите метод 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 на onCreate чтобы уведомить фрагмент, что он должен участвовать в обработке меню опций.


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

  1. добавить метод setHasOptionsMenu (true)вonCreate(Bundle savedInstanceState) метод.

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

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

пример:

активность

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

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

setHasOptionsMenu(true)

В моем случае, мне нужно меню, чтобы обновить webview внутри определенного фрагмента, для этого я использовал:

фрагмент:

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;

}

меню "Файл".в 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>

на menu.xml вы должны добавить все пункты меню. Затем вы можете скрыть элементы, которые вы не хотите видеть в исходной загрузки.

.в 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 () для вызова элементов меню в вашем классе фрагментов.

FragmentClass.java

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

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

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

}

вам нужно использовать меню.очистить () перед раздуванием меню.

@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

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

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


Если вы хотите добавить свое меню custom

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

меню Файл:

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

ваш код в порядке. В методе отсутствовал только супер:

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

Я сходил с ума, потому что ни один из ответов здесь не работал для меня.

чтобы показать меню, я должен был позвонить: setSupportActionBar(toolbar)

готово!

Примечание: Если ваш toolbar view не находится в том же макете активности, который вы не можете использовать вызов выше непосредственно из класса activity, в этом случае вам нужно будет получить эту активность из класса fragment, а затем вызвать setSupportActionBar(toolbar). Запоминание: ваш класс activity должен расширять AppCompatActivity.

надеемся, что этот ответ поможет вам.


TL; DR

использовать android.support.v7.widget.Toolbar и вобще:

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

Автономная Панель Инструментов

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

фрагмент.onCreateOptionsMenu (): инициализация содержимого Меню стандартных опций хоста фрагментов.

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

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


настройка меню параметров после создания вида фрагмента работала хорошо для меня.

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

моя проблема была немного другая. Я все сделал правильно. Но я унаследовал неправильный класс для действия, в котором находится фрагмент.

чтобы быть ясным, если вы переопределяете onCreateOptionsMenu(Menu menu, MenuInflater inflater) во фрагменте убедитесь, что класс activity, в котором размещен этот фрагмент, наследует android.support.v7.app.ActionBarActivity (в случае, если вы хотите поддерживать ниже уровня API 11).

я унаследовал android.support.v4.app.FragmentActivity для поддержки уровня API ниже 11.


одну вещь я бы добавил к этому и причину, по которой это не работало для меня.

это похоже на ответ Napster.

  1. убедитесь, что активность хостинга вашего фрагмента расширяется AppCompatActivity, а не FragmentActivity!

    public class MainActivity extends AppCompatActivity {
    
    }
    

    из ссылки Google документация для FragmentActivity:

    Примечание: Если вы хотите реализовать действие, которое включает в себя панель действий, вместо этого следует использовать класс ActionBarActivity, который является подклассом этого класса, позволяет использовать API фрагментов на уровне API 7 и выше.

  2. чтобы обновить ответ Napster -- ActionBarActivity теперь, будучи устаревшим, используйте AppCompatActivity вместо.

  3. при использовании AppCompatActivity, также убедитесь, что вы установили "тема деятельностиTheme.AppCompat или аналогичная тема" (Google Doc).

Примечание: android.support.v7.app.AppCompatActivity является наследником android.support.v4.app.FragmentActivity класса (см. AppCompatActivity ref doc).


в папке меню сделать .меню 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
                }
            });

}

Если все вышеперечисленное не работает, вам нужно отладить и убедиться, что функция onCreateOptionsMenu была вызвана (путем размещения журнала отладки или записи...)

если он не запущен, возможно, ваша тема Android не поддерживает панель действий. Открываем AndroidManifest.xml и установите значение для android:theme с темой поддержки панели действий:

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

на onCreate метод add 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);
}