简体   繁体   English

OnCreateOptionsMenu() 未在 Fragment 中调用

[英]OnCreateOptionsMenu() not called in Fragment

I have an app which got one activity with 2 fragments placed horizontally.我有一个应用程序,它有一个活动,其中 2 个片段水平放置。

In my activity I inflated menu using onCreateOptionsMenu() using which I am able to display actionbar options menu.在我的活动中,我使用onCreateOptionsMenu()膨胀菜单,使用它我能够显示操作栏选项菜单。 But when I try to update the action bar menu items from one of my fragment, the onCreateoptionsmenu() is not called.但是,当我尝试从我的片段之一更新操作栏菜单项时,不会调用onCreateoptionsmenu() So, I'm not able to update the action bar options menu.所以,我无法更新操作栏选项菜单。

The code in my activity is as below:我的活动中的代码如下:

myActivity.java我的活动.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 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();          
        }

     }
   }

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

If you are using a theme that does not support ActionBar, then OnCreateOptionsMenu() will not be called automatically, even you wrote all Java codes properly.如果您使用的主题支持 ActionBar,那么即使您正确编写了所有 Java 代码,也不会自动调用 OnCreateOptionsMenu()。

You can open AndroidManifest.xml, change the value of android:theme to "@android:style/Theme.Holo.Light.DarkActionBar", or any other themes that support ActionBar.您可以打开 AndroidManifest.xml,将android:theme的值更改为“@android:style/Theme.Holo.Light.DarkActionBar”,或任何其他支持 ActionBar 的主题。

this worked for me这对我有用

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

    setHasOptionsMenu(true);
    View view = inflater.inflate(R.layout.sample, null);
}

Also, make sure that the Toolbar instance you're passing to另外,请确保您传递给的 Toolbar 实例

setSupportActionBar(toolbar);

in your Activity is not null , because you won't get an exception if it is indeed null and you will lose a couple of hours like I did.在你的 Activity 不是null ,因为如果它确实为null你不会得到异常并且你会像我一样失去几个小时。

I used ButterKnife to bind the views, but accidentally placed setSupportActionBar(toolbar) before I actually made the call to ButterKnife.bind()我使用ButterKnife绑定视图,但在我实际调用ButterKnife.bind()之前不小心放置了setSupportActionBar(toolbar) ButterKnife.bind()

Simply tell the host activity that your fragment has options menu in its constructor. 只需告诉宿主活动您的片段在其构造函数中有选项菜单。

\n

public YourFragment() {setHasOptionsMenu(true);} public YourFragment() {setHasOptionsMenu(true);}

Although it worked for me, it is discouraged as noted in comment from @aldorain虽然它对我有用,但正如@aldorain 的评论中所指出的那样不鼓励

Applications should generally not implement a constructor.应用程序通常不应实现构造函数。 The first place application code can run where the fragment is ready to be used is in onAttach(Activity), the point where the fragment is actually associated with its activity.应用程序代码可以在准备使用片段的地方运行的第一个位置是 onAttach(Activity),片段实际与其活动相关联的点。

So put setHasOptionsMenu(true) in onCreateView() or onAttach() instead.所以将 setHasOptionsMenu(true) 放在 onCreateView() 或 onAttach() 中。

I you have a theme that doesn't provide you an AppBar by default and you are using a toolbar view to provide this feature instead, DON'T FORGET TO call setSupportActionBar(toolbar) in the onCreate() method of the activity that hosts your fragments.我有一个默认情况下不为您提供 AppBar 的主题,并且您正在使用工具栏视图来提供此功能,请不要忘记在承载您的活动的 onCreate() 方法中调用 setSupportActionBar(toolbar)碎片。

After that call setHasOptionsMenu(true) in your onCreate() fragment method.在您的 onCreate() 片段方法中调用 setHasOptionsMenu(true) 之后。

:) :)

When using the Navigation Architecture Component the action bar is not set so it needs to be done manually:使用导航架构组件时,未设置操作栏,因此需要手动完成:

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

This one will have diminishing returns as time marches on.随着时间的推移,这个收益将会递减。 In my case it was an androidX dependency on androidx.fragment:fragment:1.3.0-alpha06 which had this bug在我的情况下,它是对 androidx.fragment:fragment:1.3.0-alpha06 的 androidX 依赖,它有这个错误

simply updating that to a stable version resolved the issue.只需将其更新为稳定版本即可解决问题。

For those who have the NoActionBar theme such as: Theme.MaterialComponents.Light.NoActionBar the solution is as follows:对于有 NoActionBar 主题如: Theme.MaterialComponents.Light.NoActionBar的解决方法如下:

Kotlin version科特林版

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

Set setHasOptionsMenu(true) in onCreateView() method in fragment.在片段的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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM