I am building a calculator app using fragment and I want the calculator fragment to show back when the back button is pressed on the menu item fragment. I have been using the addToBackStac(null) but it is not working for me.
Here is my code below
public class MainActivity extends ActionBarActivity {
FragmentManager fragmentManager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null){
fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction().addToBackStack(null);
CalculatorFragment calc = new CalculatorFragment();
fragmentTransaction.add(R.id.relLejaut, calc);
fragmentTransaction.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.item) {
About about= new About();
// Insert the fragment by replacing any existing fragment
fragmentManager.beginTransaction().addToBackStack(null).replace(R.id.relLejaut, about).commit();
return true;
}
return super.onOptionsItemSelected(item);
}
}
You need to first add() or replace() a fragment in FragmentTransaction and then call addToBackStack() for it to work.
Call it this way:
fragmentManager.beginTransaction().replace(R.id.relLejaut,about).addToBackStack(null).commit();
Related
This is my scenario: I have three fragments and I only want to show an action bar in one of those fragments. In the activity that creates the fragments, I currently have this code which correctly creates the menu bar:
#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_view_report, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_view_report) {
Intent intent = new Intent(getApplicationContext(), ViewReportActivity.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}
Then in one of the fragments of which I am trying to hide the menu bar I have this code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.action_view_report).setVisible(false);
super.onPrepareOptionsMenu(menu);
}
Does anyone have any idea of what I am doing wrong or a suitable solution?
Thanks in advance
I created fragment and arrange its visibilty based onclick event of menu item. When i click first, it works properly but click again fragment visibility not hide. Explanation of image; When i click settings gray fragment is showing, when click again i want to hide gray fragment but it is not doing this stuff.
Here is my code;
#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_main, menu);
MenuItem item = menu.findItem(R.id.action_settings);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
if (findViewById(R.id.frameLayout) != null)
{
FragmentTest fragmenttest = new FragmentTest();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (fragmenttest.isVisible()) {
ft.hide(fragmenttest);
} else {
if (fragmenttest.isAdded()) {
} else {
ft.add(R.id.frameLayout, fragmenttest, "Hello Fragment");
}
ft.show(fragmenttest);
}
ft.commit();
}
return false;
}
});
return true;
}
move
FragmentTest fragmenttest = new FragmentTest();
to the top of activity.
I have an ActionBar activity with a FrameLayout and a menu. when the user clicks the menu item I replace the fragment with the relevant new fragment. However, I cannot see an obvious way to remove the menu item for the selected fragment.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
StudyFragment startFragment = new StudyFragment();
startFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add
(R.id.container, startFragment).commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_study:
replaceFragment((Fragment)new StudyFragment());
break;
case R.id.action_list:
replaceFragment((Fragment)new ListFragment());
break;
// etc
}
return super.onOptionsItemSelected(item);
}
private void replaceFragment(Fragment f) {
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, f);
transaction.addToBackStack(null);
transaction.commit();
}
The Google documentation on changing menus says to disable the menu in onPrepareOptionsMenu - but how will I know which item has been selected?
--Solution Implemented--
Using Muhammed Refaat's solution below I added two new members to the class:
private Menu activityMenu;
private MenuItem curMenuItem;
Set them in onCreateOptionsMenu
activityMenu = menu;
curMenuItem = activityMenu.findItem(R.id.action_study);
curMenuItem.setVisible(false);
And changed them on onOptionsItemSelected
curMenuItem.setVisible(true);
curMenuItem = activityMenu.findItem(id);
curMenuItem.setVisible(false);
First get the item you want to remove :
MenuItem item = menu.findItem(R.id.your_action);
then set it's Visibility false :
item.setVisible(false);
and if the problem is in getting the menu (as it's not in the fragment), you can easily get a context from the activity that contains the menu and get the menu by it.
Inside your fragment you will have to use setHasOptionsMenu(true); in order to access options menu from within your fragment.
Code (inside your second fragment where you wanna hide the item):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO your code to hide item here
super.onCreateOptionsMenu(menu, inflater);
}
Similarly, for your fragment where you want to show that MenuItem you can do the similar thing.
In the fragment where you want to hide the Item
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item=menu.findItem(R.id.action_search);
item.setVisible(false);
and in onCreate() of your fragment
setHasOptionsMenu(true);
Adding to Muhammed's answer above. Once the item has been set as invisible, you may need to also disable the item. Note Google's comment: "Even if a menu item is not visible, it may still be invoked via its shortcut (to completely disable an item, set it to invisible and disabled)" under setVisible() in the MenuItem documentation.
Thus:
item.setVisible(false);
item.setEnabled (false);
Add below codes into your fragment
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item = menu.findItem(R.id.save);
item.setVisible(false);
}
// create Boolean variable in the main activity
private var menuvisibile: Boolean = true
// while navigating fragments set the menuvisibile value and use it
// variable as part of the return statement
invalidateOptionsMenu()
menuvisibile = false
override fun onCreateOptionsMenu(menu: Menu?): Boolean
{
val menuInflater = menuInflater
menuInflater.inflate(R.menu.notification,menu)
return menuvisibile
}
working well for me.
I have a problem with adding the fragment transactions to the back stack. I have a Main activity in which I populate my layout with a Menu Fragment:
public class MainActivity extends ActionBarActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getFragmentManager().beginTransaction().add(R.id.frag_container, new MainMenuFragment()).commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Then, inside the MainMenuFragment, the user chooses some option which results in replacing the menu fragment with some other fragment:
public class MainMenuFragment extends Fragment implements OnItemClickListener{
GridView grid;
FragmentManager manager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main_menu_fragment, container, false);
manager = getActivity().getFragmentManager();
grid = (GridView) root.findViewById(R.id.gridView1);
grid.setAdapter(new MenuTileAdapter(getActivity()));
grid.setOnItemClickListener(this);
return root;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentTransaction trans = manager.beginTransaction();
if (position == 0){
trans.replace(R.id.frag_container, new BasicSettingsFragment());
trans.addToBackStack(null);
trans.commit();
}
}
}
For what i understand, this should make it so that when the user presses back button on their device, they will be brought back to the menu fragment, but instead this quits the app. What am i doing wrong?
In your Activity overwrite:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
And probably you need to use in every commited fragment transaction:
FragmentTransaction.addToBackStack(null);
Your code is a mixup, you use ActionBarActivity from appcompat and not using getSupportFragmentManager() and the fragments import should be the appcompat one if you decide to use it. If not, use Activity instead of ActionBarActivity and the simple Fragment import with FragmentManager
Add this to your activity android:configChanges="keyboardHidden|orientation|screenSize"
This will stop your activity from restarting when you rotate.
use setRetainInstance(true) on fragments.
You are not adding the MainMenuFragment to the back stack. You can try this one on your activity:
getFragmentManager().beginTransaction().add(
R.id.frag_container, new MainMenuFragment()).
addToBackStack(null).commit();
When you add or replace a fragment with the FragmentManager, you need to manually add the old fragment to the backstack with addToBackStack() before calling commit().
I'm using the NavigationDrawer in my app and replace the fragment when clicking a item in the drawer. My problem I have is that the menu items in the ActionBar are not updated when I change the fragment.
I've followed this tutorial https://www.grokkingandroid.com/adding-action-items-from-within-fragments/ closely but it's still not working in my app.
Adding some code snippets of the parent activity and one of the Fragments here.
What I need is to display the other menu items of the contact form fragment (R.menu.contactform_send_menu) when the initial fragment gets replaced with ContactFormFragment.java.
public class MainActivity extends FragmentActivity implements ActionBar.OnNavigationListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle(R.string.app_name);
// Set up the action bar to show a dropdown list.
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
createNavigationDrawer(savedInstanceState);
}
private final int DRAWER_MAIN = 0;
private final int DRAWER_CONTACT = 5;
// update the main content by replacing fragments
private void selectItem(int position) {
Fragment fragment = null;
Bundle args = new Bundle();
boolean isFragment = false;
switch (position) {
case DRAWER_MAIN:
fragment = new WelcomeSectionFragment();
args.putString(WelcomeSectionFragment.ITEM_NAME, dataList.get(position).getItemName());
args.putInt(WelcomeSectionFragment.IMAGE_RESOURCE_ID, dataList.get(position).getImgResID());
getActionBar().setTitle(R.string.app_name);
isFragment = true;
break;
case DRAWER_CONTACT:
fragment = new ContactFormFragment();
args.putString(ContactFormFragment.ITEM_NAME, dataList.get(position).getItemName());
args.putInt(ContactFormFragment.IMAGE_RESOURCE_ID, dataList.get(position).getImgResID());
getActionBar().setTitle(R.string.contactform_title);
isFragment = true;
break;
default:
break;
}
if (isFragment) {
fragment.setArguments(args);
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
setTitle(dataList.get(position).getItemName());
mDrawerLayout.closeDrawer(mDrawerList);
}
}
}
and the fragment:
public class ContactFormFragment extends Fragment {
public ContactFormFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ca = getActivity();
Reachability.registerReachability(ca.getApplicationContext());
settings = ca.getSharedPreferences(Konstanten.PREFERENCES_FILE, 0);
member = new Gson().fromJson(settings.getString(Konstanten.MEMBER_OBJECT, null), Member.class);
latoFontLight = Tools.getFont(ca.getAssets(), "Lato-Light.ttf");
latoFontBold = Tools.getFont(ca.getAssets(), "Lato-Bold.ttf");
// Update action bar menu items?
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Do something that differs the Activity's menu here
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
if (Build.VERSION.SDK_INT >= 11) {
// selectMenu(menu);
inflater.inflate(R.menu.contactform_send_menu, menu);
}
}
}
When debugging I can see that setHasOptionsMenu(true); gets called in onCreate() and I also get into the onCreateOptionsMenu() of ContactFormFragment.java. I just don't understand why the action bar keeps its initial menu items and doesn't replace them. What am I missing?
Thanks for any help.
Try putting setHasOptionsMenu(true); inside the onCreateView()of your ChildFragment.java
I don't see one in the code you posted.
I got it working! The problem I had was that I added a custom drop down menu to the main fragment. So each time I change the fragment through the drawer navigation I manually have to remove that drop down menu and when returning to the main fragment I will re-add it.
Here is what I did:
In the parent activity:
MainActivity.java:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.signin_menu, menu);
getMenuInflater().inflate(R.menu.clear_search_history_menu, menu);
// Search
// Associate searchable configuration with the SearchView
getMenuInflater().inflate(R.menu.search_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
getMenuInflater().inflate(R.menu.signin_menu, menu);
getMenuInflater().inflate(R.menu.clear_search_history_menu, menu);
// Search
// Associate searchable configuration with the SearchView
getMenuInflater().inflate(R.menu.search_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.search).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
// This is the selection of the drawer (stripped some code to keep it short)
private void selectItem(int position) {
Fragment fragment = null;
Bundle args = new Bundle();
boolean isFragment = false;
ActionBar actionBar = getActionBar();
switch (position) {
case DRAWER_MAIN:
fragment = new WelcomeSectionFragment();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setListNavigationCallbacks(new GameSystemsAdapter(getActionBarThemedContextCompat(), allSystemsPlusEmpty), this);
actionBar.setTitle(R.string.app_name);
isFragment = true;
break;
case DRAWER_FAVORITES:
fragment = new FavoritesMainFragment();
// Remove System-Select Drop-Down
actionBar.setListNavigationCallbacks(null, null);
actionBar.setNavigationMode(0);
actionBar.setTitle(R.string.favorites);
isFragment = true;
break;
case DRAWER_TOP_MEMBERS:
fragment = new TopMembersFragment();
// Remove System-Select Drop-Down
actionBar.setListNavigationCallbacks(null, null);
actionBar.setNavigationMode(0);
actionBar.setTitle(R.string.top_members_top_helping);
isFragment = true;
break;
default:
break;
}
if (isFragment) {
fragment.setArguments(args);
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
setTitle(dataList.get(position).getItemName());
mDrawerLayout.closeDrawer(mDrawerList);
}
}
and here the part of the fragment(s):
ChildFragment.java
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (Build.VERSION.SDK_INT >= 11) {
selectMenu(menu);
}
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
selectMenu(menu);
}
private void selectMenu(Menu menu) {
parentActivity.getMenuInflater().inflate(R.menu.contactform_send_menu, menu);
}
If there are any better solutions I'm very interested in your ideas.
There are two cases to consider:
You want all action items to come from within fragments exclusively.
You also have action items that should be global and are defined within the activity.
Let's begin with option 2 since it's the most common case.
If you have fragment specific items and global items at the same time, you do not want to use onCreateOptionsMenu() within the fragment. The reason is that it would look weird - even if it worked. The fragment actions would be added right after creating the fragment, while the global items would be added after the drawer has closed (by default). I think no user would like that.
What you could do to still let the fragment decide which items to display is to create an interface for all fragments to implement. This could define one method which would return the menu id for the menu to inflate or -1 if no menu should be inflated.
In case of option 1, I can only assume that you clear() the menu within the Activity's onCreateOptionsMenu(). Otherwise it wouldn't delete the fragments' menu entries. So just get rid of the clear() and all should be fine.