I want my activity to handle click on options menu items from fragment. and menu item from fragment showed at activity's menu. However, onOptionsItemSelected is not triggered when I click the button. I followed instructions from [this]([1]: (Deprecated) Fragment onOptionsItemSelected not being called) but it not work. The code is as following:
Activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_save:
L.d("appointment: action save clicked");
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Fragment:
#Override
protected void doOnCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.make_appointment_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".appointment.MakeAppointmentActivity">
<item
android:id="#+id/action_save"
android:title="#string/action_save"
app:actionLayout="#layout/menu_item_save_btn"
app:showAsAction="always" />
</menu>
edit:
The fragment is added through transaction, I guess it was the culprit?
onCreate from Activity:
#Override
protected void doOnCreate(Bundle savedInstanceState) {
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.make_appointment_edit_title);
}
// 创建并初始化Fragment
// savedInstanceState != null的时候,是指onSaveInstanceState被调用,此时UI部分会被恢复
if (savedInstanceState == null && getIntent() != null) {
String buyerName = getIntent().getStringExtra(EXTRA_BUYER_NAME);
String listingTitle = getIntent().getStringExtra(EXTRA_LISTING_TITLE);
String appointmentStatus = getIntent().getStringExtra(EXTRA_APPOINTMENT_STATUS);
float oppositeUserLatitude
= (float) getIntent().getDoubleExtra(EXTRA_LOCATION_LATITUDE, DEFAULT_UNKNOW_LATITUDE);
float oppositeUserLongitude
= (float) getIntent().getDoubleExtra(EXTRA_LOCATION_LONGITUDE, DEFAULT_UNKNOW_LONGITUDE);
MakeAppointmentFragment makeAppointmentFragment
= MakeAppointmentFragment.newInstance(buyerName, listingTitle
, appointmentStatus, oppositeUserLatitude, oppositeUserLongitude);
getSupportFragmentManager().beginTransaction()
.replace(R.id.make_appointment_fragment_placeholder, makeAppointmentFragment)
.commit();
}
}
I think you should override public boolean onOptionsItemSelected (MenuItem item) inside your Fragment if I do not miss remember. In case of you want to handle it in your Activity, cast and call ((YourActivity)getActivity). onOptionsItemSelected(item); inside your overrided onOptionsItemSelected fragment.
Related
I'm having a ToolBar made as ActionBar in a Fragment. I'm able to add ActionBar menu items but I'm not able to receive click response when I click on any ActionBar menu item.
I have read a lot of similar questions, I tried all but I'm still facing issue, so asked a question here.
The Fragment
public class DetailFragment extends Fragment {
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
setHasOptionsMenu(true);
return inflater.inflate(R.layout.project_detail, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mToolBar = (Toolbar)view.findViewById(R.id.tb_toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(mToolBar);
mToolBar.setTitle(R.string.project_details);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.project_detail_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.options:
// do something
break;
}
return true;
}
In my case in code above, onOptionsItemSelected is not even getting called.
Any pointers why ?
The Activity where I'm inflating this Fragment -
public class TestJust extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_just);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, new ProjectDetailFragment());
ft.commit();
}
}
project_detail_menu.xml -
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<item
android:id="#+id/options"
android:title="options"
android:icon="#android:drawable/ic_menu_more"
app:showAsAction="always"/>
</menu>
Most probably your problem is that you're always returning true from the activity's onOptionsItemSelected method.
When you return true, you consume the click event inside the method in the activity, that's why the click event never reaches the onOptionsItemSelected method inside your fragment.
Try this
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear()
inflater.inflate(R.menu.project_detail_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.options:
// do something
return true;
default:
return super.onOptionsItemSelected(item);
}
Solution:
You are calling setHasOptionsMenu(true); in onCreateView()
Please call that method in onCreate()
Like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
Calling this method in onCreate() ensures that the menu must participate in Fragment.
Then,
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu_items, menu);
}
Finally,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.options:
// do something
break;
}
return super.onOptionsItemSelected(item);
It should work now.
initialize option in onCreateOptionMenu then check it. you only inflate menu, use without initialize option, first initialize then use it.
like: MenuItem item = menu.findItem(R.id.option);
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
MenuItem item = menu.findItem(R.id.option);
}
switch (item.getItemId()) {
case R.id.options:
// do something
return true;//<- Here you need to return true because breaking compile from this line returns default false;
default:
return super.onOptionsItemSelected(item);
}
I have an android Activity with a bottom menu navigation bar, That navigates between three fragments and a single top menu item that should open a new activity, But the top menu ActionBar item is not responding to click events. Maybe there is something am missing? Or should I be handling the menu from within my fragments?
Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set Network Connection Listener
setConnectionListener(this);
//check the network connectivity when activity is created
checkConnection();
BottomNavigationView bottomNavigation = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomNavigation.setOnNavigationItemSelectedListener(this);
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, HomeFragment.newInstance());
transaction.commit();
// Used to select item programmatically
// bottomNavigation.getMenu().getItem(0).setChecked(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.top, menu);
// return super.onCreateOptionsMenu(menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.i(TAG, "Menu Clicked " + item.getItemId());
switch (item.getItemId()){
case R.id.tab_cart:
Intent intent = new Intent(this, CartActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
My Menu top.xml res menu file
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.shopcentra.activities.MainActivity">
<item
android:id="#+id/tab_cart"
android:icon="#mipmap/cart"
android:title="#string/cart"
app:actionLayout="#layout/notification_layout"
app:showAsAction="always">
</item>
</menu>
I can't see where you've added a View.OnClickListener on the "tab_cart". If you have set one, please share that code as well otherwise, add an OnCLickListener on that view and see if the problem persists then as well.
EDIT: code to add OnClickListener on menu item:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuItem tabCartMenuItem = menu.findItem(R.id.tab_cart);
View notificationActionView = menuItem.getActionView();
notificationActionView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(tabCartMenuItem));
}
});
}
Try adding this code to your onCreateOptionsMenu() method.
I have an ActionBarActivity and one Fragment. The Activity has no menu inflated, while the Fragment has a menu with two buttons. Fragment menu is visible, but the buttons don't react at all when tapped. At debugging I can see that both onCreateOptionsMenu() for Fragment and Activity get called, but when tapping buttons no onOptionsItemSelected() gets called, neither from Activity nor from Fragment.
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
Fragment
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = (NavigationActivity)getActivity();
setHasOptionsMenu(true);
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState){
return (ScrollView) inflater.inflate(R.layout.tutoring_detail, container, false);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.query_details_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.accept_query:
respondToQuery(true);
return true;
case R.id.decline_query:
respondToQuery(false);
return true;
default:
break;
}
return false;
}
Menu to be displayed in Fragment
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<item
android:id="#+id/accept_query"
android:orderInCategory="100"
app:showAsAction="always"
android:checkable="true"
style="?android:attr/borderlessButtonStyle"
app:actionViewClass="android.widget.ImageButton"/>
<item
android:id="#+id/decline_query"
android:orderInCategory="101"
app:showAsAction="always"
android:checkable="true"
style="?android:attr/borderlessButtonStyle"
app:actionViewClass="android.widget.ImageButton"/>
</menu>
In the Activity class,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
return false;
}
In the Fragment,
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(getActivity(), "called " + item.getItemId(), Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
}
You must use super.onOptionsItemSelected(item) in the parent activity's onOptionsItemSelected(...) method.
From Activity | Android Developers:
Derived classes should call through to the base class for it to perform the default menu handling.
Try moving setHasOptionsMenu(true) inside of the onCreateView() method in your Fragment instead of onCreate().
I had a similar issue after making special layout for my action button (I made an Image Button and needed to pad it and change some other things so I had to use layout for it).
Then onOptionsItemSelected lost connection with this imageButton so I just use clickListener for it inside onCreateOptionsMenu. It might not be the best practice, maybe there is a better solution, but this is what solve my problem.
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.picker_list_menu, menu);
MenuItem itemDone = menu.findItem(R.id.menu_done);
MenuItemCompat.setActionView(itemDone, R.layout.menu_layout_done);
menuDoneIB = (ImageButton) MenuItemCompat.getActionView(itemDone);
itemDone.getActionView().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//your code..
}
});
}
Try using oncreateview
public static class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
If you have dynamically changed menu item, for instance, a badge menu (https://stackoverflow.com/a/16648170/2914140 or https://stackoverflow.com/a/26017587/2914140), you should initialize the item in onCreateOptionsMenu and re-set setOnClickListeners after every change of the item.
In my case:
private MenuItem menuItem;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_catalog, menu);
menuItem = menu.findItem(R.id.action_badge);
writeBadge(0);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_badge) {
// Your code.
return true;
}
return super.onOptionsItemSelected(item);
}
private void writeBadge(int count) {
MenuItemCompat.setActionView(menuItem, R.layout.item_badge);
RelativeLayout layout = (RelativeLayout) MenuItemCompat.getActionView(menuItem);
// A TextView with number.
TextView tv = (TextView) layout.findViewById(R.id.badge);
if (count == 0) {
tv.setVisibility(View.INVISIBLE);
} else {
tv.setVisibility(View.VISIBLE);
tv.setText(String.valueOf(count));
}
// An icon, it also must be clicked.
ImageView imageView = (ImageView) layout.findViewById(R.id.image);
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(menuItem);
}
};
menuItem.getActionView().setOnClickListener(onClickListener);
imageView.setOnClickListener(onClickListener);
}
I am passing the click event to fragment from the activity. This worked for me.
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
return getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getFragments().size() - 1)
.onOptionsItemSelected(item);
}
I know this question has been asked and but I am unable to solve my problem after looking at those answer. I have an Activity with a Fragment.
In fragment, I have added the toolbar and I want to handle toolbar menu item click events from the fragments.
In menu, I have added a single share button. I am getting the click event callback for the Up navigation (arrow home button) but I am not getting click event callback for the share button in my fragment.
Can some points me at what I am doing wrong here.
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.rahul.haridasasampada.details.DescriptionActivity">
<item
android:id="#+id/action_share"
android:title="Share"
android:orderInCategory="100"
app:showAsAction="always"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
</menu>
I have added toolbar to the fragment layout.
My Activity's code -
public class DescriptionActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_description);
if (savedInstanceState == null) {
Article articleExtra = (Article) getIntent().getParcelableExtra(DescriptionFragment.ARGS_EXTRA);
DescriptionFragment descriptionFragment = DescriptionFragment.newInstance(articleExtra);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, descriptionFragment)
.commit();
}
}
#Override
protected void onResume() {
super.onResume();
getSupportActionBar().setTitle(R.string.app_name_in_kannada);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_description, menu);
Log.d("debug", "activity : onCreateOptionsMenu");
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
Log.d("debug","activity: action home has clicked");
onBackPressed();
return false;
case R.id.action_share:
Log.d("debug","activity: action share has clicked");
return false;
}
return super.onOptionsItemSelected(item);
}
}
My Fragments code -
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// some code
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ActionBarActivity actionBarActivity = (ActionBarActivity) getActivity();
Toolbar toolbar = (Toolbar) getView().findViewById(R.id.toolbar_actionbar);
actionBarActivity.setSupportActionBar(toolbar);
toolbar.setOnMenuItemClickListener(this);
toolbar.inflateMenu(R.menu.menu_description);
}
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_share:
if (menuItem.getItemId() == R.id.action_share)
Log.d("debug","action share has clicked");
return true;
}
return false;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
Log.d("debug", "fragment : onCreateOptionsMenu");
MenuItem shareMenuItem = menu.findItem(R.id.action_share);
mShareActionProvider =(ShareActionProvider)MenuItemCompat.getActionProvider(shareMenuItem);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
Log.d("debug","fragment : action home has clicked");
return true;
case R.id.action_share:
Log.d("debug","fragment: action share has clicked");
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View detailFragmentView = inflater.inflate(R.layout.fragment_description, null);
return detailFragmentView;
}
From Android Docs, for Fragment:
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater)
Initialize the contents of the Activity's standard options menu. You should place your menu items in to menu. For this method to be called, you must have first called setHasOptionsMenu(boolean).
so you want to control actionbar menu in Fragment, then you have to call setHasOptionsMenu method better in Fragment's onCreate(...):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
also important is that you should not use inflateMenu and onCreateOptionsMenu both together for same ToolBar, inflateMenu is for standalone without setting ToolBar as ActionBar.
Suggestion:
keep one ToolBar in Activity as ActionBar for your App, and another ToolBar standalone inside Fragment.
Hope this help!
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
public class MyFragment extends Fragment implements Toolbar.OnMenuItemClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list, container, false);
Toolbar toolbar= (Toolbar) getActivity().findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.menu_main);
toolbar.setOnMenuItemClickListener(this);
return rootView;
}
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_menu:
//do sth here
return true;
}
return false;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.training1_fragment, container,
false);
setHasOptionMenu(true);
return v;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_save :
{
//Write here what to do you on click
return true;
}
}
return super.onOptionsItemSelected(item);
}
You should getPointer toolbar from your activity class and inflate menu in fragment class.
You can look this ex:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = ((DescriptionActivity ) getActivity());
Toolbar tollbar=getView.findViewById(R.id.your_toolbar);
activity.setSupportActionBar(toolbar);
activity.toolbar.inflateMenu(R.menu.menu_search);
activity.toolbar.setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_search:
break;
}
return false;
}
Please refer this for click of the Fragment optionMenu click link.
EDIT:
This question was for the deprecated sherlock action bar. Android support library should be used instead now
I have added an action bar menu option called share for my fragment which appears but the selection event is not being caught
I am adding it like this
#Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
MenuItem item = menu.add(0, 7,0, R.string.share);
item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
Trying to capture it in both the fragment and the fragment activity like
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 7:
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
startActivity(Intent.createChooser(share, "Share Text"));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
and I have setHasOptionsMenu(true); in the onCreate().
Same problems happened to me:
onMenuItemSelected events didn't get called in Fragment
Searched google cann't find a solution, and add onMenuItemSelected method in FragmentActivity doesn't solve it.
Finally resolve it by following reference to http://developer.android.com/guide/topics/ui/actionbar.html
Note: If you added the menu item from a fragment, via the Fragment class's onCreateOptionsMenu callback, then the system calls the respective onOptionsItemSelected() method for that fragment when the user selects one of the fragment's items. However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected() on the activity before calling the same callback for the fragment.
Which means only if you don't have that menu item handler in onOptionsItemSelected() on the activity, the onOptionsItemSelected() on the fragment will be called.
Code as following
-----Remove the handler for R.action.add on FragmentActivity):
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
popBackStack();
return true;
case R.id.action_search:
searchAction();
return true;
case R.id.action_logout:
userLogout();
return true;
//case R.id.action_add:
//return true;
default:
return super.onOptionsItemSelected(item);
}
}
And the handler for R.action.add on Fragment looks like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("onOptionsItemSelected","yes");
switch (item.getItemId()) {
case R.id.action_add:
add();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Finally, remember to add
setHasOptionsMenu(true);
in your onCreate method in Fragment
I had the same problem, but I think it's better to summarize and introduce the last step to get it working:
Add setHasOptionsMenu(true) method in your Fragment's onCreate(Bundle savedInstanceState) method.
Override onCreateOptionsMenu(Menu menu, MenuInflater inflater) (if you want to do something different in your Fragment's menu) and onOptionsItemSelected(MenuItem item) methods in your Fragment.
Inside your Activity's onOptionsItemSelected(MenuItem item) method, make sure you return false when the menu item action would be implemented in Fragment's onOptionsItemSelected(MenuItem item) method.
An example:
Activity
#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;
}
Fragment
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;
}
I have noticed that the solution people gave you was to implement the code for your menue item in the activity rather then the fragment.
I think it will look much more orgenized if you had implemented the code in the fragment rather then the activity 'cos in my opinion it looks better.
To do so, do as follows :
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.SomeIDInTheMenueOfTheActivity:
{
//something();
break;
}
default:
//do something default and add the code under :
return super.onOptionsItemSelected(item);
}
return true;
}
Fragment
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.SomeIDInFragmentMenue:
{
break;
}
default:
return super.onOptionsItemSelected(item);
}
return true;
}
Now the lines (and the likes): "return super.onOptionsItemSelected(item);" in the activity and fragment are super important, because as if you will follow the code in debug, you will see that the menue events functions will be called first on the Activity, and if the item did not match the id's in the activity's switch-case, the degault line : "super.onOptionsItemSelected(item);" will call the onOptionsItemSelected function on the fragment, as we wanted.
(if you have many fragments, make sure to have that line in them as well, as the calling hirarchy can be somewhat complicated).
I'm using actionbarsherlock. This worked for me:
1) Create dummy_menu.xml menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
<item
android:title=""
android:showAsAction="never"
android:id="#+id/dummyMenu"
/>
2) In activity inflate the menu like this:
#Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.dummy_menu,menu);
return super.onCreateOptionsMenu(menu);
}
3) In fragments onCreateView call setHasOptionsMenu(true) and override onCreateOptionsMenu and onOptionsItemSelected also hide the dummyMenu like this (in fragment)
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_actions, menu);
MenuItem item = menu.findItem(R.id.dummyMenu);
item.setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
Hope it helps someone.
Edit for actionbar sherlock use
I had to use
public boolean onMenuItemSelected(int featureId, MenuItem item) {
in the main activity to capture the menu item
it's so simple you can do that in your fragment to make sure that your action will listen correctly:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
From the documentation, it should solve by this steps:
If you in Activity Using the addMenuProvider() API directly:
class ExampleActivity : ComponentActivity(R.layout.activity_example) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Add menu items without overriding methods in the Activity
addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
})
}
}
If you in Fragment Using the addMenuProvider() API
class ExampleFragment : Fragment(R.layout.fragment_example) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// The usage of an interface lets you inject your own implementation
val menuHost: MenuHost = requireActivity()
// Add menu items without using the Fragment Menu APIs
// Note how we can tie the MenuProvider to the viewLifecycleOwner
// and an optional Lifecycle.State (here, RESUMED) to indicate when
// the menu should be visible
menuHost.addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
}
I had this problem. It was because I was overiding the wrong method
onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item)
is what I used.
Make sure you are using the right one!
You are not chaining to the superclass in the activity methods. Please have onCreateOptionsMenu() return super.onCreateOptionsMenu(menu), and have onOptionsItemSelected() return super.onOptionsItemSelected(item) (except for the item that you are handling, which should return true to indicate that you have handled the event)
you must add this code toolbar.bringToFront(); next set toolbar in your activity
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
...
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle("Yazd");
setSupportActionBar(toolbar);
toolbar.bringToFront(); // <<= add here
...