【问题标题】:OnCreateOptionsMenu() not called in Fragment片段中未调用 OnCreateOptionsMenu()
【发布时间】:2021-08-12 10:04:11
【问题描述】:

我有一个应用程序,它有一个活动,水平放置了 2 个片段。

在我的活动中,我使用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 android-fragments


    【解决方案1】:

    在您的片段的onCreateView() 方法中,您需要调用setHasOptionsMenu(true) 来告诉宿主活动您的片段具有要添加的菜单选项。

    【讨论】:

    • 我进行了更改,但应用程序在 11-27 01:55:34.468 崩溃:E/AndroidRuntime(12294):原因:java.lang.ClassCastException:com.android.internal.view。 menu.MenuItemImpl 无法转换为 android.widget.SearchView
    • 是的,我发现了问题。忘记为 searchView 添加 getActionView()。
    • 另外你必须使用 void 类型的 onCreateOptionsMenu(Menu menu, MenuInflater inflater) Boolean 类型不起作用
    • 如果您在 Activity 的布局中使用 Toolbar,请确保在 Activity 中调用 setSupportActionBar(your_toolbar)。否则setHasOptionsMenu 无效。
    【解决方案2】:

    如果您使用的是支持ActionBar的主题,那么即使您正确编写了所有Java代码,也不会自动调用OnCreateOptionsMenu()。

    您可以打开 AndroidManifest.xml,将 android:theme 的值更改为“@android:style/Theme.Holo.Light.DarkActionBar”,或任何其他支持 ActionBar 的主题。 p>

    【讨论】:

    • 我正在使用支持库中的工具栏和 Theme.AppCompat.Light.NoActionBar 作为主题,我面临同样的问题...没有显示选项菜单..请帮助
    • 我通过调用toolbar.inflateMenu(R.menu.menu_custom);解决了它
    • 在你的activity中调用setSupportActionBar(mToolbar),Fragments中的onCreateOptionsMenu就会被自动调用。
    【解决方案3】:

    这对我有用

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
    
        setHasOptionsMenu(true);
        View view = inflater.inflate(R.layout.sample, null);
    }
    

    【讨论】:

      【解决方案4】:

      另外,请确保您传递给的 Toolbar 实例

      setSupportActionBar(toolbar);
      

      在你的活动中不是null,因为如果它确实是null,你不会得到异常,你会像我一样失去几个小时。

      我使用ButterKnife 绑定视图,但在我实际调用ButterKnife.bind() 之前意外放置了setSupportActionBar(toolbar)

      【讨论】:

      • 哈里斯,你太棒了。感谢您分享这一点!我遇到了这个确切的问题,因为我使用的是 Kotlin,而且很多时候您不必执行 findViewById 等...即可获得所需的视图。
      【解决方案5】:

      只需告诉宿主 Activity,您的片段在其构造函数中有选项菜单。

      public YourFragment() {setHasOptionsMenu(true);}

      虽然它对我有用,但正如@aldorain 的评论中所指出的那样不鼓励

      应用程序通常不应实现构造函数。首先 应用程序代码可以在片段准备好使用的地方运行 在onAttach(Activity)中,就是fragment实际所在的点 与其活动相关联。

      所以将 setHasOptionsMenu(true) 放在 onCreateView() 或 onAttach() 中。

      【讨论】:

      【解决方案6】:

      如果您有一个默认情况下不提供 AppBar 的主题,而您正在使用工具栏视图来提供此功能,请不要忘记在活动的 onCreate() 方法中调用 setSupportActionBar(toolbar)托管您的片段。

      在 onCreate() 片段方法中调用 setHasOptionsMenu(true) 之后。

      :)

      【讨论】:

        【解决方案7】:

        使用导航架构组件时,未设置操作栏,因此需要手动完成:

        @Override
        public void onViewCreated( @NonNull View view, @Nullable Bundle savedInstanceState ) {
            NavController navController = Navigation.findNavController( view );
        
            AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( R.id.nav_1, R.id.nav_2, R.id.nav_3 ).build();
        
            Toolbar toolbar = view.findViewById( R.id.toolbar );
            ((AppCompatActivity) requireActivity()).setSupportActionBar( toolbar );
            CollapsingToolbarLayout collapsingToolbarLayout = view.findViewById( R.id.collapsing_toolbar );
        
            NavigationUI.setupWithNavController( collapsingToolbarLayout, toolbar, navController, appBarConfiguration );
        }
        

        【讨论】:

          【解决方案8】:

          随着时间的推移,这个收益将递减。在我的情况下,它是一个 androidX 对 androidx.fragment:fragment:1.3.0-alpha06 的依赖,它有 this bug

          只需将其更新为稳定版本即可解决问题。

          【讨论】:

            【解决方案9】:

            对于那些有 NoActionBar 主题的人,例如: Theme.MaterialComponents.Light.NoActionBar解决方法如下:

            Kotlin 版本

            override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
                super.onViewCreated(view, savedInstanceState)
                setupToolbar()
                
            }
            
            private fun setupToolbar() {
                setHasOptionsMenu(true)
                // The other option is using val toolbar = findViewById(R.id.toolvar) 
                // and add as parameter instead of the binding option
                (activity as AppCompatActivity).setSupportActionBar(binding.toolbar) 
                (activity as AppCompatActivity).supportActionBar?.setDisplayShowTitleEnabled(false)
            }
            
            override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
                super.onCreateOptionsMenu(menu, inflater)
                inflater.inflate(R.menu.my_menu, menu)
            }
            
            
            override fun onOptionsItemSelected(item: MenuItem): Boolean {
                return when (item.itemId) {
                    R.id.menu_item_1
                        //TODO: implement something here for option 1
                        true
                    }
                    R.id.menu_item_2 -> {
                        //TODO: implement something here for option 2
                        true
                    }
                    else -> super.onOptionsItemSelected(item)
                }
            }
            

            【讨论】:

              【解决方案10】:

              在片段的onCreateView()方法中设置setHasOptionsMenu(true)

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

              【讨论】:

              • 您好,欢迎来到 SO。请不要只发布未注释且格式错误的纯代码答案,因为这并不能解释问题中描述的问题究竟是什么。查看here,了解有关什么是好的答案的一般提示。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-03-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多