I'm learning how to create an app and have figured out how to build a login activity and a menu for logging out that returns you to the login layout. However, if I navigate through my different layouts/activities, the menu item for logging out duplicates. I believe it's due to having the menu created on each layout, but I'm not sure how to change it so that it doesn't duplicate.
Here's my fragment.
public class UserFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
return inflater.inflate(R.layout.activity_user_fragment, container, false);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_logout, menu);
}
}
My LoginActivity.class
public class LoginActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Button b1login = (Button) findViewById(R.id.btlogin);
Button b2login_cancel = (Button) findViewById(R.id.btcancel_login);
assert b1login != null;
b1login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText ed1 = (EditText) findViewById(R.id.etuser_name);
EditText ed2 = (EditText) findViewById(R.id.etpassword);
if (ed1.getText().toString().equals(getText(R.string.user_id)) &&
ed2.getText().toString().equals(getText(R.string.user_password))) {
Toast.makeText(getApplicationContext(), R.string.successful_login,
Toast.LENGTH_SHORT).show();
setContentView(R.layout.activity_clients);
} else {
Toast.makeText(getApplicationContext(), R.string.unsuccessful_login,
Toast.LENGTH_SHORT).show();
}
}
});
assert b2login_cancel != null;
b2login_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.exit(0);
}
});
}
//Menu option logout return to login screen.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_item_logout) {
Intent i = new Intent(this, LoginActivity.class);
this.startActivity(i);
return true;
}
return super.onOptionsItemSelected(item);
}
public void addClient(View view) {
setContentView(R.layout.activity_new_client);
}
public void submitClient(View view) {
setContentView(R.layout.activity_sessions);
}
public void cancelClient(View view) {
setContentView(R.layout.activity_clients);
}
public void newSession(View view) {
setContentView(R.layout.activity_new_session);
}
public void cancelSessionCompletion(View view) {
setContentView(R.layout.activity_sessions);
}
public void cancelSession(View view) {
setContentView(R.layout.activity_sessions);
}
}
Fragment layout.
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_item_logout"
android:icon="#drawable/ic_logout"
android:title="#string/logout"
app:showAsAction="ifRoom|withText" />
</menu
EDIT:
I deleted the fragment where I initially created the menu as well as the menu code from the UserFragment and hard coded the menu itself into the LoginActivity class, which fixed the duplication issue.
Code adding menu.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
However, the menu now shows on the login screen. How do I prevent it from showing there?
For having different menu items in different activities you need to create different menu xml layouts.
So one file named menu.xml is already there in res folder. You need to create new xml file in same folder.
Then in java code of that activity :- in override Oncreateoptionmenu inflate the menu you want.
Here is what you need to do:
In your LoginActivity class, you want to NOT inflate the menu because you don't want users to do see the logout option.
In your Activity that loads after Login, you actually want to inflate the Logout menu - well, because you want them to see and use that option.
In your code, I see that your fragment uses the method :
setHasOptionsMenu(true);
What you can do here is use an if statement to see if a user has logged in before and if not, set that to true otherwise, do nothing (which is like setting to false).
You can reuse the menu in other activities if you want to enable users to Logout from those activities or just leave them it out!
I hope this helps!
EDIT
According to your sample code above, your first part shows what you would do inside a Fragment class - you setHasOptionsMenu(true). Now, it seems that you have two logout menus, in the activity and in the fragment - which I do not see where you have used your Fragment in your LoginActivity - unless it is somewhere else in a different activity!
Similar to my answer here, https://stackoverflow.com/a/63008005/5916188, a work-around would be to remove the menu each time, if it exists, before adding it.
Note that the existing menu is removed item by item (R.id...) while the inflated one is added by menu (R.menu...) as usual.
This way, you can keep the menu in the fragment. Like this:
#Override public void onCreateOptionsMenu (#NonNull Menu menu, #NonNull MenuInflater
inflater)
{
super.onCreateOptionsMenu (menu, inflater);
removeMenuItemIfPresent (menu, R.id.menu_search_options);
removeMenuItemIfPresent (menu, R.id.menu_sample_filter1);
removeMenuItemIfPresent (menu, R.id.menu_sample_filter2);
inflater.inflate (R.menu.menu_search_menu, menu);
}
private void removeMenuItemIfPresent (#NonNull Menu menu, int resourceIDToRemove)
{
MenuItem menuItemToRemove = menu.findItem (resourceIDToRemove);
if (menuItemToRemove != null) {
menu.removeItem (menuItemToRemove.getItemId ());
}
}
Related
My Fragment class:
Toolbar toolbar;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
toolbar = getView().findViewById(R.id.toolbar3);
toolbar.inflateMenu(R.menu.menufragmentmain);
setHasOptionsMenu(true); //i also tried putting this function in oncreate function
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Toast.makeText(getActivity(), "i never enter this function also" , Toast.LENGTH_LONG).show();
super.onCreateOptionsMenu(menu,inflater);
inflater.inflate(R.menu.menufragmentmain, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(getActivity(), "i never enter this function" , Toast.LENGTH_LONG).show();
//some switch cases.....
return super.onOptionsItemSelected(item);
}
I've got a stupid error which I cant find unfourtantly. I've got a simple toolbar for my fragment. In onViewCreated I inflate my actionbar menu with my toolbar.
The issue is that the functions onCreateOptionsMenu and 'onOptionsItemSelected' are never called. I've got no clue why.
Things i checked in other similar questions with the same issue:
I checked if my main activity has a onCreateOptionsMenu or'onOptionsItemSelected'. It doesn*t
Checked if my style class has NOT: android:theme="#android:style/Theme.Black.NoTitleBar
None of the points unfourtantly work. What did I miss. Do I need to check something else?
As per the Fragment-owned app bar guide which explains how to use a Fragment-owned Toolbar, you do not use any of the setHasOptionsMenu(), onCreateOptionsMenu(), or onOptionsItemSelected() APIs - those are only used for activity owned app bars.
Instead, you would follow the guide for handling menu click events by using the Toolbar APIs:
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
toolbar = getView().findViewById(R.id.toolbar3);
toolbar.inflateMenu(R.menu.menufragmentmain);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(getActivity(), "onMenuItemClick called" , Toast.LENGTH_LONG).show();
//some switch cases.....
return true;
}
});
}
Set up the toolbar in the host Activity. Then override the menu handling in each Fragment wherever necessary.
Here's some generic scaffolding (with comments):
public class MyFragment extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Report that this Fragment has an options menu
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
// Inflate then menu, and THEN call super()
// Note the order of the invocations
inflater.inflate(R.menu.my_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
// Handle menu item selections
final int itemId = item.getItemId();
switch(itemId) {
case R.id.my_menu_option_x: ...; return true;
case R.id.my_menu_option_y: ...; return true;
case R.id.my_menu_option_z: ...; return true;
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'm working to implement a SearchView on my Fragment's RecyclerView as shown here. When the user taps the search button I want the Menu Item for the SearchView to Override the toolbar and display the area for them to search. If I don't use my custom style for the toolbar it works fine but when I do it get the images below.
Here is what I am currently getting:
This is the class that the EventListActivity inherits from:
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.eventcalendar_activity_fragment);
// Manages our fragments. We can call it to add a fragment to an activity in code
FragmentManager fm = getSupportFragmentManager();
// Check if fragment of R.id already exits
// The FragmentManager saves out the list of fragments on rotation destruction or memory reclaim
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
// If the the fragment does not exist, create it
if(fragment == null) {
fragment = createFragment();
// Create a new fragment transaction, include one add operation in it, and then commit it
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
}
}
}
This creates the fragment that manages and works with the RecyclerView:
public class EventListActivity extends SingleFragmentActivity {
#Override
protected Fragment createFragment() {
// Setting arguments for the new fragment created from the intent from EventFeedResultWrapper
EventListFragment fragment = new EventListFragment();
fragment.setArguments(getIntent().getExtras());
return fragment;
}
}
Fragment that holds the RecyclerViewthat the SearchView will interface with. This is where the search menu button is inflated. It is where I've been trying to modify the toolbar:
public class EventListFragment extends Fragment {
private RecyclerView mEventRecyclerView;
private EventAdapter mAdapter;
// Telling the FragmentManager that it is
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
((AppCompatActivity)getActivity()).getSupportActionBar().setCustomView(R.layout.action_bar_center);
View sabView = ((AppCompatActivity)getActivity()).getSupportActionBar().getCustomView();
TextView titleTxtView = (TextView) sabView.findViewById(R.id.action_bar_title);
titleTxtView.setText("Events Calendar");
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowCustomEnabled(true);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.eventcalendar_fragment_event_list, container, false);
mEventRecyclerView = (RecyclerView) view.findViewById(R.id.event_recycler_view);
// RecyclerView requires a layout manager to work, layout manager is in charge of position items on screen
mEventRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
// Populate the menu instance
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.eventcalendar_menu, menu);
}
// When we edit a EventActivity this saves it back to the EventListActivity
// onResume over onStart because we cannot assume the activity will be stopped
// when another activity is in front of it. If the other activity is transparent
// then the activity might just get paused. If it is paused then onStart() will not be called
// but on resume will be called.
// NOTE: In general onResume() is the safest place to take action to update a fragment's view
#Override
public void onResume() {
super.onResume();
updateUI();
}
private void updateUI() {
// Read in the events saved in to EventFeedResultWrapper by the Async task in ParseEventFeedTask
EventFeedResultWrapper wrapper = (EventFeedResultWrapper) getArguments().getSerializable(ParseEventFeedTask.EXTRA_RESULTS_LIST);
// Make sure wrapper is not null, it will NEVER be null
if(wrapper == null){
throw new RuntimeException("Error: The wrapper is null!");
}
// Get all the events from the wrapper/serializable
List<Event> events = wrapper.getEventFeedResults();
// Gets the context that we don't use rofl
EventCal eventCal = EventCal.get(getActivity());
// Add all the events we got from the wrapper to our event manager eventCal
eventCal.addEvents(events);
// Check to see if the EventAdapter is already setup
if(mAdapter == null) {
mAdapter = new EventAdapter(events);
mEventRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
}
//Adapter here - removed code since it doesn't do anything with the toolbar
//RecycleView onClickLister - removed code since it doesn't do anything with the toolbar
}
This is the custom XML Style
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/action_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:textSize="24dp"/>
</LinearLayout>
Event 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/action_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
Did you missed android:orientation="vertical". The text is displaying vertically. You want horizontal right?
Oh nvm i didn't understood it at first. The problem must be the inflating of the custom view, for some reason it seems it keeps the original view there and inflated it somewhere else. Give me 1s i'll update the answer when i find the issue
Check here: getSupportActionBar().setCustomView(view) does not fill entire actionbar
Similar problem. First and Second answer
EDIT2: Remove the code from EventListFragment onCreate. You don't need to inflate a searchView, you can use the default one.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
super.onCreateOptionsMenu(menu, inflater);
setOptionsMenu(menu);
}
public void setOptionsMenu(Menu menu) {
MenuItem search = menu.findItem(R.id.search);
SearchView searchView;
/**
* Setup the SearchView
*/
SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
final boolean[] modifiedOriginal = {false};
searchView = (SearchView) search.getActionView();
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(((Activity) context).getComponentName()));
MenuItemCompat.setOnActionExpandListener(search, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
...
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
...
return true;
}
});
final EditText et = ButterKnife.findById(searchView, android.support.v7.appcompat.R.id.search_src_text);
et.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
String s = editable.toString();
if (!s.equals("") && !s.equals(" ")) {
...
}
}
});
ButterKnife.findById(searchView, android.support.v7.appcompat.R.id.search_close_btn).setOnClickListener(
view -> {
...
et.setText("");
}
);
}
}
You can leave your menu xml as it is.
I am very new to Java and android apps.
I am trying to open a screen when the user clicks on a button. The button is called "Company"
I have a MainActivity.java and a Company.java
MainActivity looks like:
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// If your minSdkVersion is 11 or higher, instead use:
// getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
/** Called when the user clicks the Company button */
public void onClick(View view) {
// Do something in response to button
Intent intent = new Intent(this, TheCompany.class);
startActivity(intent);
}
}
But nothing happens when the user clicks on the button Company.
I have a Company Java file and a Company XML file, but they don't get called. I suspect it is the way they are being called from here.
Would really appreciate some help. Also let me know if I need to post other bits of code, like the activity_main.xml.
Thanks!
If you want to open a new activity with his own java.class by a button, just replace this:
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button)findViewById(R.id.Company);
btn.setOnClickListner(new View.OnClickListner(){
#Override
public void onClick(View v){
Intent activityChangeIntent = new Intent(MainActivity.this,TheCompany.class)
MainActivity.this.starActivity(activityChangeIntent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
the onclick() method is never called!
You have forgotten to set android:onClick in you layout xml file or to set the OnClickListener programmatically in code (see below):
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View button = findViewById(R.id.myButtonId);
button.setOnClickListener(new OnClickListener(){
public void onClick (View v){
startIntent();
}
});
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// If your minSdkVersion is 11 or higher, instead use:
// getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
/** Called when the user clicks the Company button */
private void startIntent() {
// Do something in response to button
Intent intent = new Intent(this, TheCompany.class);
startActivity(intent);
}
}
You seem to say you have Company.java, but in your intent you are trying to access TheCompany.class. The file name needs to match the public class in your Company.java. So you either need to have a Company.java file with a Company class or TheCompany.java file with TheCompany class.
I suspect this is setup correctly, otherwise if you've added android:onClick in your XML file you'd be getting errors.
It's worth posting the XML for the button, sockeqwe is most likely right.
I have Action Bar in my application. I am adding action items using menu.xml. I am using action bar-compat as my support library. I observed a weird issue where my action items are getting duplicated.
I am finding this issue randomly when leave my device idle or work with other applications. Please find the screen shot and my code below:
private LoginWebActivity mContext;
private final String TAG = "LoginFragment";
// for metrics
private String mPageNameSignIn = "signin";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.webview, container, false);
return mView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mContext = (LoginWebActivity) getActivity();
initFragment();
}
#Override
public void onResume() {
super.onResume();
}
/**
* Initialises the views and variables of the fragment.
*/
#SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
protected void initFragment() {
mWebView = (WebView) mView.findViewById(R.id.webView);
Bundle b = mContext.getIntent().getExtras();
if (b != null) {
mUrl = b.getString(Constants.EXTRA_WEB_LOGIN_URL);
}
super.initFragment();
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.signin, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Navigate
switch (item.getItemId()) {
case R.id.menu_item_signup:
mContext.onSignUpClick();
break;
case android.R.id.home:
if (!goBack())
getActivity().finish();
default:
break;
}
return super.onOptionsItemSelected(item);
}
My XML :
<?xml version="1.0" encoding="utf-8"?>
<item
android:id="#+id/menu_item_signup"
allergy:showAsAction="ifRoom"
android:title="#string/sign_up">
</item>
You must clear your menu object before adding items. I had the same problem and this was the best solution that I've found.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.signin, menu);
super.onCreateOptionsMenu(menu, inflater);
}
Pretty late to this party, but for anyone that comes across this via the Google like I did, here's the real problem.
You didn't post your Activity code that's creating the Fragment, but I will venture to guess that it looks something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Fragment fragment = ...
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
The problem with this is that when the activity goes through its lifecycle (which would happen "when leave my device idle or work with other applications", as you say), the system will save and restore the state of fragments for you. But with this code, you also are adding a new fragment to your Activity, so you end up with multiple fragments running in your activity, each adding an item to the menu.
While the posted workaround will address the duplicate menu entries issue, it would leave these extra fragment instances lying around, which is obviously not what you want.
The correct fix is a simple null check:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
if (savedInstanceState == null) {
Fragment fragment = ...
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
}
Since the system will indicate the activity is being recreated with a non-null Bundle for the savedInstanceState parameter, you check this to determine whether you should be creating and adding a new fragment.
Hope that helps.
i used Renan Bandeira's great solution and i had some error so i changed it a little bit and worked for me too . then I'm sharing my experience : maybe it become helpful again all credit goes to him for great solution .
#Override
public void onCreateOptionsMenu(Menu menu ) {
menu.clear();
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu."your current activity name ", menu);
return true;
}
I facing the same problem and exactly as state by #Szymon "I add menu option from the fragment, I create multiple fragments?" So my solution was look like below.
onCreate :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu, menu);
menu.findItem(R.id.action_one).setVisible(true);
menu.findItem(R.id.action_two).setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
onPrepare :
#Override
public void onPrepareOptionsMenu(Menu menu) {
if (isAdded()
&& !isDetached()
&& isVisible()
&& !isRemoving()
)
{
// show the menu
if (menu.findItem(R.id.action_one).isVisible())
menu.findItem(R.id.action_one).setVisible(true);
// hide the menu
if (menu.findItem(R.id.action_two).isVisible())
menu.findItem(R.id.action_two).setVisible(false);
}
}
You should use the following method instead and you will not see the duplicates anymore (notice that it has only a Menu object as argument)
#Override
public boolean onCreateOptionsMenu( Menu menu )
{
getMenuInflater().inflate( R.menu.main_activity_menu, menu );
return true;
}