how to go back to the previous fragment [duplicate] - java

This question already has an answer here:
Navigation View Global Action Back State
(1 answer)
Closed 1 year ago.
I have a search button, with an actionViewClass. When this button is clicked a new fragment opens, and I want when the back button is clicked to go back to the previous fragment.
PS: I am using navigation graph
My toolbar_menu.xml
<item
android:id="#+id/search"
android:title="Pesquisar"
android:orderInCategory="103"
android:icon="#drawable/ic_search"
android:iconTint="#color/colorPrimary"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
MainActivity.java
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.search:
getSupportFragmentManager().beginTransaction()
.replace(R.id.navHostFragment, new ContaFragment())
.commit();
break;
}
return false;
}
});

try adding the fragment to backstack
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.navHostFragment, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}
this question has a good answer and explanation here How to resume Fragment from BackStack if exists

Related

How to fix bottom navigation bar not showing correctly

I'm having the problem that when I trying to switch between the menu item. The menu item will not pointing to the correct icon.
here is the flow when i found this problem
starting at the (Home)fragment,then press on the second menu item (Features )
case R.id.nav_home:
//home fragment transaction
actionBar.setTitle("Home");
HomeFragment fragment1 = new HomeFragment();
FragmentTransaction fragmentTransaction1 = getSupportFragmentManager().beginTransaction();
fragmentTransaction1.replace(R.id.content, fragment1, "");
fragmentTransaction1.commit();
break;
second menu item (features) will go to features activity
case R.id.nav_features:
//features fragment transaction
startActivity(new Intent(DashboardActivity.this, FeaturesActivity.class));
break;
close features activity and back to (Home) fragment
onBackPressed();
bottom navigation still pointing to second menu item (features).
how can I make the system point to the correct menu item ?
You should return a boolean for this method:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
//...
}
do this :
case R.id.nav_home:
//home fragment transaction
actionBar.setTitle("Home");
HomeFragment fragment1 = new HomeFragment();
FragmentTransaction fragmentTransaction1 =
getSupportFragmentManager().beginTransaction();
fragmentTransaction1.replace(R.id.content, fragment1, "");
fragmentTransaction1.commit();
return true; // add this line and remove break;
if you don't want to select icon after click, you can return false.

Fragment Transaction shows Tabs Fragment below

I'm making an app that has launches with a Swiping Tabs Fragment, but I also want to have a Preferences menu using Fragment Transaction. When I press the Settings button in my app, the preferences menu does appear and is interactive, but the layout seems to be transparent showing the Tabs below. Is there anything that can be done to fix this, or is there a better method?
Code that calls the Preferences Menu from the Options:
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getFragmentManager().popBackStackImmediate();
break;
case R.id.logout:
FirebaseAuth.getInstance().signOut();
finish();
startActivity(new Intent(this, Activity_Main.class));
break;
case R.id.action_settings:
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new Fragment_Settings()).addToBackStack(null)
.commit();
break;
}
return true;
}
Code that calls Tabs Fragments:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new Fragment_Flower();
case 1:
// Games fragment activity
return new Fragment_Overview();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}
}
Initialising Transaction in onCreate:
startService(new Intent(this, SensorListener.class));
if (b == null) {
// Create new fragment and transaction
Fragment newFragment = new Fragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
//Replace whatever is in the fragment_container view with this
// fragment,
// and add the transaction to the back stack
transaction.replace(android.R.id.content, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
Any help will be greatly appreciated!
Just set background color in your layout file. It may avoid transparent backgound.

Go back to fragment of Activity A from Activity B

In my app, am using a navigation drawer (in Fragment A) to navigate to fragments:
public void displayView(int viewId){
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (viewId) {
case R.id.nav_menu:
fragment = new MenuFragment();
title = getString(R.string.menu_title);
viewIsAtHome = false;
break;
case R.id.nav_reservation:
fragment = new ReservationFragment();
title = getString(R.string.reservation_title);
viewIsAtHome = false;
break;
...
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
// set the toolbar title
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
}
displayView() is called in onNavigationItemSelected:
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
displayView(item.getItemId());
return true;
}
Now, in ReservationFragment I am displaying a list of reservations and a FloatingActionButton to start Activity B where the user can add a reservation if there are no reservations. When the user is done adding a reservation, I want to display it in the Reservation fragment. This requires me to "go back" to the Fragment.How do I accomplish this since Activity B knows nothing about Activity A?
What I've tried:
I tried creating a method in Activity A like this:
public void navigateToFragment(int viewId) {
displayView(R.id.nav_reservation);
}
and then called this method from Activity B:
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new MainActivity().navigateToFragment(R.id.nav_reservation);
//MainActivity is Activity A
}
});
the app crashes due to a nullPointerException in displayView() from the line:
String title = getString(R.string.app_name);
This isn't surprising since am creating a new MainActivity object that knows nothing about the previous state of the Activity, right?
This question mirrors my problem but is based on Settings so I can't really use the answer in my case.
How do I accomplish this task?
There are three quick methods that come to my mind. First you can start activityB with startActivityForResult and handle the result in activityA after user does what he wants in activityB. Second you can set activityA as singleTop and before finishing activityB you can startActivityA with clearTop an intent flag called clear_top(https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP).
Last but not the least, you can connect two activity by binding service in both activities and communicate via that service that you bound.

Implementing back stacks with fragments

I'm attempting to implement a back stack while using fragments, but when using the Back button, I keep getting taken out of the app to the home screen.
Activity opens fragment A; Fragment A has a clickable TextView that opens fragment B (this works). Hitting BACK should return me to fragment A, but it takes me to the home screen instead.
Here is the activity's call to the opening of fragment A in onCreate:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_layout_container, new FragmentLogin(), "fragment_login")
.addToBackStack("login_screen")
.commit();
Log.d("Back", getFragmentManager().getBackStackEntryCount() +" <- Entry Count at LoginActivity.onCreate" );
At this point, the Log prints 0 <- Entry Count at LoginActivity.onCreate. Something I've done wrong keeps this from printing 1.
Then, the Fragment A has this listener:
forgottenPassword.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_layout_container, new FragmentForgottenPassword(), "fragment_password")
.addToBackStack("forgotten_password")
.commit();
Log.d("Back", getFragmentManager().getBackStackEntryCount() + " <- Entry Count at FragmentLogin.onCreateView.Listener");
}
});
The Log here prints 1 <- Entry Count at FragmentLogin.onCreateView.Listener. Here, the listener works and opens fragment B - but the back button returns me to the home screen.
Use this in your Activity it should pop out the fragments already added to backstack
#Override
public void onBackPressed()
{
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Try Like This,
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
} else {
getFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
transaction.replace(R.id.fragment_layout_container, fragment);
transaction.commitAllowingStateLoss();
getFragmentManager().executePendingTransactions();
}
and Used it like this,
replaceFragment(new FragmentForgottenPassword(), true);
There is a GitHub library that will do this work for you!https://github.com/rathodchintan/Fragment-Back-StackWhenever you are displaying any new fragment, just push that fragment into stack using following code.
//here this fragment is our first fragment
homeListFragment = new HomeListFragment();
fragmentStack.push(homeListFragment);It has many other stack options too.

How to hide all other fragments

Just for coding practice, I'm creating a small game.
Currently I added a optionmenu, and if a item is selected a new fragment is shown. Thanks working good.
My problem is that the game fragment should never be destroyed. Only hidden.
If I'm using my code below both frames (about and help) can exist at the same time. But if I use replace on R.id.container the game fragment will stop (there is a timer in there).
Here is my Java code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
getFragmentManager().popBackStack();
return true;
case R.id.action_about:
if (getFragmentManager().findFragmentByTag("about_fragment") == null) {
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// Gets the game fragement so it can be hidden
Fragment fragment = getFragmentManager().findFragmentByTag("game_fragment");
getFragmentManager().beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.add(R.id.container, new AboutFragment(), "about_fragment")
.hide(fragment)
.addToBackStack("about_fragment")
.commit();
return true;
}
return true;
case R.id.action_help:
if (getFragmentManager().findFragmentByTag("help_fragment") == null) {
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// Gets the game fragement so it can be hidden
Fragment fragment = getFragmentManager().findFragmentByTag("game_fragment");
getFragmentManager().beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.add(R.id.container, new HelpFragment(), "help_fragment")
.hide(fragment)
.addToBackStack("help_fragment")
.commit();
return true;
}
return true;
default:
return super.onOptionsItemSelected(item);
}
Here my XML with the container:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DoNothingGame"
tools:ignore="MergeRootFrame" />
I could ask in every case in the switch if the other fragments are shown and hide them, but I think code will blow up a LOT if I use, for example, 10 or 20 menu items.
So.. Is there a way to hide every fragment except the new one?
Thanks for your help!
Maybe a little bit late but I manage to implement it like this:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
for (Fragment frag : fm.getFragments()){
ft.hide(frag);
}
ft.commit();

Categories