I handle my back navigation like such:
When creating / committing a Fragment:
getSupportFragmentManager()
.beginTransaction()
.addToBackStack("ToDoFragment")
.replace(R.id.content_frame, fragmentR, fragmentR.getClass().getSimpleName())
.commit();
When catching a back button press:
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
// If navigation drawer is open, close it
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
setDrawerState(true);
displayMenu(true);
}
}
This works fine for my Fragments, but I wish to do the same for my PreferenceFragment, that I call like such:
getFragmentManager().beginTransaction()
.add("ToDoFragment")
.replace(R.id.content_frame, new SettingsFragment()).commit();
But when pressing my back nav. button it does not bring me back to the previous Fragment, instead it overlaps my Settings view and my previous Fragment.
What am I missing / not understanding?
EDIT:
I have added getFragmentManager().popBackStackImmediate(); to my onBackPressed() method, I do not have any view overlapping, but when going into my settings and pressing back, the Fragment is empty.
Using a PreferenceFragment you canĀ“t override onBackPressed() in this case use onDetach() :
#Override
public void onDetach() {
super.onDetach();
//Do your process here!
}
Instead of using 'add' in manager use 'addtoBackStack' Because add retains the existing fragments and adds a new fragment which means existing fragment will be active. Hence back button is not called for existing fragment.
getFragmentManager().beginTransaction()
.addToBackStack("ToDoFragment")
.replace(R.id.content_frame, new SettingsFragment()).commit();
Related
I have Base Activity including NavigationView with 2 menu items. On start it loads Home fragment having background image inside it. Each loads specific fragment. When I select Terms & Conditions menu item, it loads T&C fragment & when I press back button it simply kills it.
However, when I select About Us menu item, it loads About Us fragment but I need to press BACK button twice to kill it. I need to know why does it happen?
Part of Code in AppBaseActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
HomeFragment homeFragment = new HomeFragment();
fragmentTransaction.add(R.id.body_container, homeFragment, "");
fragmentTransaction.commit();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
navigationView.getMenu().findItem(item.getItemId()).setChecked(true);
switch (item.getItemId()) {
case R.id.nav_terms :
fragmentTransaction = fragmentManager.beginTransaction();
TCFragment tcFragment = new TCFragment();
fragmentTransaction.replace(R.id.body_container, tcFragment, "");
fragmentTransaction.commit();
break;
case R.id.nav_about_us :
fragmentTransaction = fragmentManager.beginTransaction();
AboutUsFragment aboutUsFragment = new AboutUsFragment();
fragmentTransaction.replace(R.id.body_container, aboutUsFragment, "");
fragmentTransaction.commit();
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
All fragments simply have overridden onCreateView() by inflating respected xml only. No code is written in both fragments yet.
You can stop back hardware navigation if you want.
Simply using onBackPressed() without super.onBackPressed()
#Override
public void onBackPressed() {
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
In my application, I have 5 fragments and the requirement is that on any given fragment, if back button is pressed, it should exit out of the application. In other words the fragments does not have any order and are independent. SO pressing the back button on any fragment will actually close the app itself.
In some fragments, I am opening other fragments using this code:
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
track nextFrag= new track();
login.this.getFragmentManager().beginTransaction()
.replace(R.id.content_frame, nextFrag, null)
.addToBackStack(null)
.commit();
However the history is still maintained, What can I do to clear the history on start of any fragment.
EDIT:
Tried this and the application does exit on pressing back, however I can still see a glimpse of previous activity and it throws some nasty exceptions.
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
finish();
}
}
I am using navigation drawer and fragment to show the component on selecting navigation option.And if user select navigation drawer option a fragment will open. So my problem is when I call a activity from fragment and when I press back button it call previous fragment but the content of that fragment remain same. What I want is when I press back button from activity it should open my fragment or recall fragment and values should be blank like first time we call the fragment.
Thanks.
Try this:-
#Override
public void onBackPressed() {
if (getTitle().equals("Title")) {
YourFragment fragment =new YourFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
} else {
super.onBackPressed();
}
}
I am using a DrawerLayout with and adding a new Fragment each time the user taps an item from the drawer menu. This works perfectly.
Within one of those fragments the user can navigate to another fragment:
private void loadArchives() {
PUCNewsArchive news_archive = new PUCNewsArchive();
getFragmentManager()
.beginTransaction()
.add(R.id.container_frame, news_archive, "news_archives")
.addToBackStack(null)
.commit();
}
This will correctly add another fragment to the stack. BUT, it does not change the action bar drawer button/icon to a back button. So, in tapping that just opens the drawer again, which is should not do. The only way to navigate back is the use the hardware back button which does go back to the previous fragment. I tried adding the following to my main Activity to see what was going on:
#Override
public void onBackPressed(){
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack();
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed();
}
}
But that is only ever called when I use the hardware back button, as the drawer button is only ever opening the drawer.
I assume this should be checking to see if it should open the drawer or navigate:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
switch(item.getItemId()) {
case android.R.id.home:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
What have I missed? Why is the drawer button never changing to a back button nor acting like one?
You don't need to use the onBackPressed().
I had a very similar situation in my app. Here is how I got it to work:
I created a method in the main activity:
public void foo(int fragment_id) {
if(fragment_id == some_id){
// keep the drawer carat
mDrawerToggle.setDrawerIndicatorEnabled(true);
}else{
// Disable the drawer carat, and enable the back button
mDrawerToggle.setDrawerIndicatorEnabled(false);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
I call this method from onResume() of each fragment, and pass it that particular fragments id. Alternatively, you can call it from the loadFragment()/loadArchives() method in your main activity. This works fine for me.
In your Navigation Activity
This activity controls all fragments in the app.
When preparing new fragments to replace others, I set the DrawerToggle
setDrawerIndicatorEnabled(false) like this:
private void loadArchives() {
PUCNewsArchive news_archive = new PUCNewsArchive();
//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getFragmentManager()
.beginTransaction()
.add(R.id.container_frame, news_archive, "news_archives")
.addToBackStack(null)
.commit();
}
in onCreateview of another fragment
call
// update the actionbar to show the up carat/affordance
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
For More reference Check This Question
I tried above suggested codes But the "up" or "Back" arrow in left side of action bar was just not showing up in my app. But luckily I was able to fix that.
Brief code:
Function to start fragment while putting the current fragment to Back Stack:
public void startFragment(){
MyFrag myFrag = new MyFrag();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frag_container ,myFrag)
.addToBackStack(null)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
}
Function to turn ON or OFF "NavigationDrawer":
public void setNavigationDrawerState(boolean isEnabled) {
if ( isEnabled ) {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();
}
else {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
toggle.setDrawerIndicatorEnabled(false);
toggle.setHomeAsUpIndicator(R.drawable.ic_keyboard_backspace_white_24dp);
toggle.syncState();
}
I downloaded the drawable: ic_keyboard_backspace_white_24dp from Material.io
The complete answer:
Disabling navigation drawer, toggling home-button/up-indicator in fragments
I am working with the navigation drawer, and having a small problem. The problem occurs When I am in my an activity, and navigate to that same activity though the navigation drawer. The activity launches new (screen popping up).
I would like the drawer to just close when the user attempts to navigate to the activity they are currently on.
Thanks for you help!
Why not just check the current Activity, pseudocode:
if (this instanceof SomeActivity){
closedrawer();
}else{
navigate to SomeActivity
}
//global reference
private DrawerLayout mDrawerLayout;
//instantiate onCreate()
mDrawerLayout= (DrawerLayout) findViewById(R.id.drawer_layout);
//close it some where, on button click...
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
mDrawerLayout.closeDrawer(Gravity.LEFT);
}
In the method you handle clicks from the navigation drawer:
// This is for the case where the user is trying to open a fragment called `NewFragment`
Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(NewFragment.TAG);
if (currentFragment == null) {
NewFragment newFragment = new NewFragment()
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment, NewFragment.TAG);
transaction.commit();
}
mDrawerLayout.closeDrawer(mDrawerList);
This works if you have added your fragments to the fragment container with the tag. I usually keep this as a public static final String in the respective fragments. For instance, NewFragment has a static String called TAG that is can be used to find it later using the fragment manager.
If the currentFragment is null, it means that is not currently added to the manager's activity nor on the back stack. In that case add the new fragment to the fragment container. If not, just simply close the navigation drawer.