OnCreateOptionsMenu () не вызывается во фрагменте

107

У меня есть приложение, в котором есть одно действие с двумя фрагментами, расположенными по горизонтали.

В своей деятельности я раздувал меню, используя onCreateOptionsMenu()которое я могу отображать меню опций панели действий. Но когда я пытаюсь обновить пункты меню панели действий из одного из моих фрагментов, onCreateoptionsmenu()функция не вызывается. Итак, я не могу обновить меню параметров панели действий.

Код в моей деятельности выглядит следующим образом:

myActivity.java

package com.andr.androidtablelist;

import java.io.IOException;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import com.andr.fragments.ListLeftFragment;
import com.andr.utils.DBHelper;

      public class TabletActivity extends Activity {
    ActionBar actionBar = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DBHelper dbhelper;
        dbhelper = new DBHelper(this);
        try {
            dbhelper.createDatabase();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        setContentView(R.layout.activity_tablet);
        actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(false);
        getFragmentManager().beginTransaction()
                .replace(R.id.master, ListLeftFragment.newInstance()).commit();
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            Toast.makeText(
                    getApplicationContext(),
                    "Back Stack Count::"
                            + getFragmentManager().getBackStackEntryCount(),
                    Toast.LENGTH_LONG).show();
            if (getFragmentManager().getBackStackEntryCount() == 1) {
                actionBar.setDisplayHomeAsUpEnabled(false);
            }
            if (getFragmentManager().getBackStackEntryCount() > 1) {
                getFragmentManager().popBackStack();

            }
            return true;

        }
        return super.onOptionsItemSelected(item);
    }

}
      // http://www.vogella.com/articles/AndroidListView/article.html

myFragment.java

      package com.andr.fragments;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;

import com.andr.androidtablelist.R;
import com.andr.helper.LazyHelper;

   public class ListLeftFragment extends Fragment{
    private static ListLeftFragment listFragment = null;

    public static ListLeftFragment newInstance(){
        listFragment = new ListLeftFragment();      
        return listFragment;
    }

     @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);


    }

     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
         View v =  inflater.inflate(R.layout.fragment_listlayout, container,false);
         getActivity().invalidateOptionsMenu();
         ListView lv = (ListView)v.findViewById(R.id.lview);
         String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
                    "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
                    "Linux", "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux",
                    "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2",
                    "Android", "iPhone", "WindowsMobile" };
         getActivity().getActionBar().setTitle("LeftList");

          ArrayList<String> list = new ArrayList<String>();
         LazyHelper lHelper = new LazyHelper(getActivity());
         list = lHelper.getLazyDetials();

           /* for (int i = 0; i < values.length; ++i) {
              list.add(values[i]);
            }
            final StableArrayAdapter adapter = new StableArrayAdapter(getActivity(),
                android.R.layout.simple_list_item_1, list);*/
            LeftListAdapter lAdapter = new LeftListAdapter(getActivity(),list);
            lv.setAdapter(lAdapter);
            lv.setOnItemClickListener(new OnItemClickListener()
            {

                @Override
                public void onItemClick(AdapterView<?> arg0, View arg1,
                        int pos, long arg3) {
                    final String clickedData = (String)arg0.getItemAtPosition(pos);
                    Bundle bundle = new Bundle();
                    bundle.putString("clickedItemName", clickedData);
                    Fragment detailFragment = DetailFormRightFragment.newInstance();
                    detailFragment.setArguments(bundle);
                    getActivity().getFragmentManager().beginTransaction().replace(R.id.details, detailFragment).addToBackStack(null).commit();
                }

            }
                    );
         return v;
    }


     @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        getActivity().getMenuInflater().inflate(R.menu.search, menu);
        SearchView searchView=(SearchView)menu.findItem(R.id.search);
        searchView.setIconifiedByDefault(true);
    } 

     @Override
    public boolean onOptionsItemSelected(MenuItem item) {

         super.onOptionsItemSelected(item);
         return false;
    }


     @Override
    public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
        /*MenuItem item;
        menu.clear();
        getActivity().getMenuInflater().inflate(R.menu.search, menu);
        SearchView searchView=(SearchView)menu.findItem(R.id.search);
        searchView.setIconifiedByDefault(true);*/
    }

     private class StableArrayAdapter extends ArrayAdapter<String> {

            HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

            public StableArrayAdapter(Context context, int textViewResourceId,
                List<String> objects) {
              super(context, textViewResourceId, objects);
              for (int i = 0; i < objects.size(); ++i) {
                mIdMap.put(objects.get(i), i);
              }
            }

            @Override
            public long getItemId(int position) {
              String item = getItem(position);
              return mIdMap.get(item);
            }

            @Override
            public boolean hasStableIds() {
              return true;
            }

          }

     private class LeftListAdapter extends BaseAdapter implements OnClickListener {
         private Context mcontext;
         ArrayList<String> listData;
         private  LayoutInflater inflater=null;
         public LeftListAdapter(Context context, ArrayList<String> listItems) {
              mcontext=context;
              listData=listItems;
              inflater = (LayoutInflater)mcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         }

        @Override
        public int getCount() {
            return listData.size();
        }

        @Override
        public Object getItem(int arg0) {
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public View getView(int position, View view, ViewGroup arg2) {
            // create a ViewHolder reference
            View vi=view;
            if(vi==null){
                vi = inflater.inflate(R.layout.item, null);
            }
            TextView text=(TextView)vi.findViewById(R.id.text);
            text.setText(listData.get(position));
            vi.setOnClickListener(this);
            return vi;
        }

        @Override
        public void onClick(View vi) {
            TextView text=(TextView)vi.findViewById(R.id.text);
            Bundle bundle = new Bundle();
            bundle.putString("clickedItemName", text.getText().toString());
            Fragment detailFragment = DetailFormRightFragment.newInstance();
            detailFragment.setArguments(bundle);
            getActivity().getFragmentManager().beginTransaction().replace(R.id.details, detailFragment).addToBackStack(null).commit();          
        }

     }
   }
Android_programmer_office
источник

Ответы:

296

В onCreateView()методе вашего фрагмента вам нужно вызвать, setHasOptionsMenu(true)чтобы сообщить активности хоста, что у вашего фрагмента есть параметры меню, которые он хочет добавить.

dangVarmit
источник
Я внес изменения, но приложение вылетает с 11-27 01: 55: 34.468: E / AndroidRuntime (12294): вызвано: java.lang.ClassCastException: com.android.internal.view.menu.MenuItemImpl не может быть переведен на android .widget.SearchView
Android_programmer_office
да, я нашел проблему. забыл добавить getActionView () для searchView.
Android_programmer_office,
2
Кроме того, вы должны использовать порового типа для onCreateOptionsMenu (меню Menu, MenuInflater Inflater) булева типа не будет работать
Bahaa Хани
15
Если вы используете Toolbarв своем макете Activity, убедитесь, что вы вызываете setSupportActionBar(your_toolbar)свой Activity. В противном случае setHasOptionsMenuне действует.
artkoenig
Ты моя любовь, братан :)
Кадир Хуссейн
30

Если вы используете тему , которая не поддерживает ActionBar, то OnCreateOptionsMenu () не будет вызываться автоматически, даже если вы правильно написали все коды Java.

Вы можете открыть AndroidManifest.xml, изменить значение android: theme на «@android: style / Theme.Holo.Light.DarkActionBar» или любые другие темы, поддерживающие ActionBar.

анимализировать
источник
Я использую панель инструментов из библиотеки поддержки и Theme.AppCompat.Light.NoActionBar в качестве темы, и я сталкиваюсь с той же проблемой ... меню параметров не отображается ...
пожалуйста,
6
Я решил это, позвонивtoolbar.inflateMenu(R.menu.menu_custom);
Дхрувам Гупта
Просто вызовите setSupportActionBar (mToolbar) в своей деятельности, и onCreateOptionsMenu во фрагментах будет вызываться автоматически.
Vít Kapitola
12

это сработало для меня

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    setHasOptionsMenu(true);
    View view = inflater.inflate(R.layout.sample, null);
}
Анисетти Нагендра
источник
11

Также убедитесь, что экземпляр панели инструментов, которому вы передаете

setSupportActionBar(toolbar);

в вашей Activity нет null, потому что вы не получите исключения, если это действительно так, nullи вы потеряете пару часов, как я.

Я использовал ButterKnife для привязки представлений, но случайно поместил его, setSupportActionBar(toolbar)прежде чем я действительно позвонил вButterKnife.bind()

продолговатый мозг Джека
источник
1
Харис, ты классный. Спасибо за то, что поделился этим! У меня была именно эта проблема, потому что я использую Kotlin, и много раз вам не нужно выполнять findViewById и т. Д., Чтобы получить нужное представление.
DWndrer
1

Просто сообщите активности хоста, что у вашего фрагмента есть меню параметров в его конструкторе.

public YourFragment () {setHasOptionsMenu (true);}

Хотя это сработало для меня, это не рекомендуется, как указано в комментарии от @aldorain

Приложения обычно не должны реализовывать конструктор. В первую очередь код приложения может запускаться там, где фрагмент готов к использованию, это onAttach (Activity), точка, в которой фрагмент фактически связан с его активностью.

Поэтому вместо этого поместите setHasOptionsMenu (true) в onCreateView () или onAttach ().

Кен Ратаначай С.
источник
Вы не должны писать свои собственные конструкторы для нестандартных фрагментов
aldorain
1
developer.android.com/reference/android/app/Fragment.html tl; dr 'Обычно приложения не должны реализовывать конструктор [Fragment].'
aldorain
0

Если у вас есть тема, которая не предоставляет вам AppBar по умолчанию, и вместо этого вы используете представление панели инструментов, чтобы предоставить эту функцию, НЕ ЗАБУДЬТЕ вызвать setSupportActionBar (панель инструментов) в методе onCreate () действия, в котором размещается ваш фрагменты.

После этого вызовите setHasOptionsMenu (true) в методе фрагмента onCreate ().

:)

Морено
источник
-2

Набор setHasOptionsMenu(true)в onCreateView()способе в фрагменте.

@Override

 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
 {
    Viewroot=inflater.inflate(R.layout.fragment_client_requestfragment,container,false);
  hideKeyboard();
    getemail = getArguments().getString("email_id");
    Log.e("email_id from activity",getemail);
    setHasOptionsMenu(true);
    return root;
}
Нимиша Патель
источник
1
Привет и добро пожаловать в SO. Пожалуйста, не публикуйте ответы, содержащие только код без комментариев и плохо отформатированный, поскольку это не объясняет, в чем именно заключалась проблема, описанная в вопросе. Посмотрите здесь несколько общих советов о том, что является хорошим ответом.
Gero