fragment back to the end , the screen is white [duplicate] - android

This question already has answers here:
White screen after going back through Fragments
(2 answers)
Closed 6 years ago.
I have a MainActivity, it has a lots of Fragment under it.
I set the return mechanism transaction.addToBackStack(null);
The function like this:
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
transaction.addToBackStack(null);
transaction.commit();
}
My issue is when I click the back button to the end, the FrameLayout is white
I tried to add
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mainFrame==null)
return super.onKeyDown(keyCode, event);
}
}
It's not working. How do I avoid this white screen when I call back the Fragment to the end ? Any help would be great!

I took #ReazMushed's suggestion and changed like this:
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() ==1) {
finish();
}else{
super.onBackPressed()
}
}
And the white screen problem is gone!

From your question what I've understood is, you have a set of Fragment which is launched one after one and when you press the back button, they disappears one after one. When the first Fragment reaches and you click the back button again, it shows a white screen.
If I'm correct, you might have to track if the first Fragment is reached and then finish the Activity.
Implement the onBackPressed function in your MainActivity. You might consider doing something like this.
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
getSupportFragmentManager().popBackStack();
else
finish(); // Finish the activity
}

Related

White screen after going back through Fragments

I've got an Android application which is working fine, but I've found an annoying bug which I don't know what else do to solve it.
My application has a single Activity (call it HomeActivity; well, plus the Preferences Activity) and lots of Fragments. HomeActivity manages the replacement of every Fragment using this method (found in this thread and especially looking into the following comment):
public void switchFragment(Fragment pFragment, String pTagFragment){
String backStateName = pTagFragment;
boolean fragmentPopped = mFragmentManager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.replace(R.id.content_frame, pFragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}
To replace a Fragment, what I do is the following:
switchFragment(new FragmentEuskalmet(), FragmentEuskalmet.FRAGMENT_NAME);
Here it's the problem: I navigate through several Fragments (say, 3 of them). Then, I wanna go back, so I press back 2 times. When I arrive to the last within the stack, a white screen is shown (i.e. white is shown in the place where the Fragment should be). The odd thing is that if I do a long press to my home button to show the recent apps and I choose again my application, the fragment gets loaded correctly.
I assume there might be something within my switchFragment method, e.g. it may be any issue related to the backStack. One important detail is that I've got written the so called empty constructor in every Fragment.
Can anybody lend me a hand? I can provide further code pieces if anybody request them.
Edit:
I've considered compulsory to type my sss method:
#Override
public void onBackPressed(){
invalidateOptionsMenu();
if(CURRENT_FRAGMENT != FragmentMapa.FRAGMENT_NAME){//"com.ingartek.bizkaimove.ui.FragmentMapa"){
mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerRightRelativeLayout);
}
if(mDrawer.isDrawerOpen(GravityCompat.START)){
mDrawer.closeDrawer(GravityCompat.START);
setToolbarSubtitle(mSubtitleAux);
}else{
setToolbarSubtitle(getString(R.string.app_name_subtitle));
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
//finish();
showExitDialog();
}else {
super.onBackPressed();
popFragment();
}
}
}
I think I should rewrite this part:
}else {
super.onBackPressed();
popFragment();
}
Solution:
As #Ajay Pandya suggested, I leave the onBackPressed() that way:
#Override
public void onBackPressed(){
invalidateOptionsMenu();
if(CURRENT_FRAGMENT != FragmentMapa.FRAGMENT_NAME){//"com.ingartek.bizkaimove.ui.FragmentMapa"){
mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerRightRelativeLayout);
}
if(mDrawer.isDrawerOpen(GravityCompat.START)){
mDrawer.closeDrawer(GravityCompat.START);
setToolbarSubtitle(mSubtitleAux);
}else{
setToolbarSubtitle(getString(R.string.app_name_subtitle));
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
//finish();
showExitDialog();
}else{
mFragmentManager.popBackStackImmediate();
}
} else {
super.onBackPressed();
}
}
}
You can manage back stack and screen for exit like
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
This is because you are adding all your fragments programmatically. On pressing back buttons, you eventually remove the first fragment that you added as well.
The reason you get it back on launching the application is because you add the fragment again.
I would suggest overwrite your back button. Whenever you pop fragment, check to see that it's not your first fragment and then pop it.

How to go switch back to the MainActivity from a fragment?

I have a MainActivity, which starts fragments, in according to a specific button pressed. When I'm under a fragment and I press the back button, the application will be closed. My idea is, when the back button is pressed, I will show the MainActivity, with all the button. I write these lines of code in the MainActivity:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
recreate();
}
return super.onKeyDown(keyCode, event);
}
Is it a good solution ? It works quite well, the only things is that between the transaction of fragment layout and the activity layout, there is a black screen for less then half second. is there any way to fix it ?
When you are adding the fragment, add it to backStack. The back press will automatically revert the fragment and shows your main activity.
Eg:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(..............);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Going back in Fragments by pressing the back button

I want to go back to another fragment by pressing the back button. I already read, that the addToBackStack (String tag) should help but it didn't really work.
Here is what I'm doing when switching fragments.
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.content_frame, new MainFragment());
ft.addToBackStack("Mainfragment");
ft.commit();
So now, the Fragment opens, and starts an AsyncTask where a loading circle appears. After the loading the data gets displayed. When I now press the back button once, the fragment goes back to the start of the AsyncTask where the loading circle is created. But the AsyncTask doesn't continue. When I press the back button again, the app closes.
I tried to add onBackPressed but it just told me, that this won't work in a Fragment. What would be the best way to go here?
Edit for clarification:
There's no error. It's just not working. It is like I don't even have the line addToBackStack –
I had the same situation before and I ended up with this solution. When you add or replace the Fragments, you need to add it to the backStack with a unique name. Then when the back button is pressed you can see which fragment was the active one with the method below inside the FragmentActivity that you created the Fragment.
private String getCurrentFragmentName() {
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
String fragmentName;
if (backStackEntryCount > 0) {
fragmentName = getSupportFragmentManager().getBackStackEntryAt(backStackEntryCount - 1).getName();
} else {
fragmentName = "";
}
return fragmentName;
}
and in on onKeyDown() method do the following.
if (keyCode == KeyEvent.KEYCODE_BACK && getCurrentFragmentName().equals("your fragment name")) {
// Handle back press for this case.
return true;
} else if (keyCode == KeyEvent.KEYCODE_BACK
&& getCurrentFragmentName().equals("your another fragment")) {
// Handle back press for another Fragment
return true;
} else {
return super.onKeyDown(keyCode, event);
}
And this is the Place how I add the Fragment with backStack
transaction.addToBackStack("Your Fragment Name");

how to go back to previous fragment on pressing manually back button of individual fragment?

I have only one activity and multiple fragments in my application.
Two main fragment A(left) and B(right).
Fragment A1 called from A
B1 called from B
B2 called from B1
All fragments have individual back buttons.
So when I press back button of fragment A1, it should go back to A, similarly when Back button from B2 is pressed, B1 appears and from B1 to B and so on.
How to implement this type of functionality?
public void onBackPressed()
{
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack();
}
I have implemented the similar Scenario just now.
Activity 'A' -> Calls a Fragment 'A1' and clicking on the menu item, it calls the Fragment 'A2' and if the user presses back button from 'A2', this goes back to 'A1' and if the user presses back from 'A1' after that, it finishes the Activity 'A' and goes back.
See the Following Code:
Activity 'A' - OnCreate() Method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityA);
if (savedInstanceState == null) {
Fragment fragInstance;
//Calling the Fragment newInstance Static method
fragInstance = FragmentA1.newInstance();
getFragmentManager().beginTransaction()
.add(R.id.container, fragInstance)
.commit();
}
}
Fragment : 'A1'
I am replacing the existing fragment with the new Fragment when the menu item click action happens:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_edit_columns) {
//Open the Fragment A2 and add this to backstack
Fragment fragment = FragmentA2.newInstance();
this.getFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(null)
.commit();
return true;
}
return super.onOptionsItemSelected(item);
}
Activity 'A' - onBackPressed() Method:
Since all the fragments have one parent Activity (which is 'A'), the onBackPressed() method lets you to pop fragments if any are there or just return to previous Activity.
#Override
public void onBackPressed() {
if(getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
}
else {
getFragmentManager().popBackStack();
}
}
If you are looking for Embedding Fragments inside Fragments, please refer the link: http://developer.android.com/about/versions/android-4.2.html#NestedFragments
#trueblue's answer got me going with one minor but annoying issue. When there is only one fragment on the backstack and you press back button, that frame is removed and the app remains active with a blank screen. User needed to press back button one more time to exit the app. I modified the original code to the following in order to handle this situation
#Override
public void onBackPressed() {
if(getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
}
else if(getFragmentManager().getBackStackEntryCount() == 1) {
moveTaskToBack(false);
}
else {
getFragmentManager().popBackStack();
}
}
When there is only 1 fragment in the backstack, we are basically telling android to move the whole app to back.
Update (and probably a better answer)
So after doing some more reading around this, I found out that you can add fragment manager transactions to back stack and then android handles back presses automatically and in a desired way. The below code snippet shows how to do that
Fragment fragment; //Create and instance of your fragment class here
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment).addToBackStack(null);
fragmentTransaction.commit();
fragmentTransaction.addToBackStack(null);
The last line shows how you add a transaction to back stack. This solves back press issue for fragments in most situations except for one. If you go on pressing back button, then eventually you will reach a point when there is only one fragment in the back stack. At this point, you will want to do one of the two things
Remove the activity housing the fragment from the back stack of the task in which activity is running. This is because you do not want to end up with a blank activity
If the activity is the only activity in the back stack of the task, then push the task in background.
In my case, it was the later, so I modified the overridden onBackPressed method from my previous answer to look like below
#Override
public void onBackPressed() {
if(getFragmentManager().getBackStackEntryCount() == 1) {
moveTaskToBack(false);
}
else {
super.onBackPressed();
}
}
This code is simpler because it has less logic and it relies on framework than on our custom code. Unfortunately I did not manage to implement code for first situation as I did not need to.
You have to implement your own backstack implementation as explained here.
You can call the popFragments() whenever you click the back button in a fragment and call pushFragments() whenever you navigate from one Fragment to other.
Just Do
getActivity().getFragmentManager().popBackStack();
Try this, Its Work for me.
public void onBackPressed() {
if (mainLayout.isMenuShown()) {
mainLayout.toggleMenu();
} else {
FragmentManager fm = getSupportFragmentManager();
Log.print("back stack entry", fm.getBackStackEntryCount() + "");
if (fm.getBackStackEntryCount() > 1) {
fm.popBackStack();
// super.onBackPressed();
// return;
} else {
if (doubleBackToExitPressedOnce) {
fm.popBackStack();
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press one more time to exit",
Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 3000);
}
}
}
Back button will traverse in the order, in which Fragments were added to backstack. This is provided as a navigation function by default. Now if you want to go to specific Fragment, you can show it from backstack.
You can handle it by adding tag in the backStack. Check my answer here :
https://stackoverflow.com/a/19477957/1572408
hope it helps
#Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
// replace your fragment here
return true;
}
return false;
}
});
}
// Happy Coding
If you press back image you have to create method first like this
private void Backpresses() {
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.contant_main, new Home()).commit();
}
then you have to call like this when you press back image..
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Backpresses();
}
});
It work fine for me.

Should the android back button be overriden

I want to go back to the last fragment in the back stack, so I want to make the back button popback the stack. Should I do this? and if so, should I override onBackPressed() or onKeyDown()?
#Override
public void onBackPressed()
{
Intent intent = new Intent(this,ABC.class);
startActivity(intent);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK ) {
// do something on back.
return true;
}
return super.onKeyDown(keyCode, event);
}
My fragments aren't being added to the back stack properly for some reason
I am using this to try to go back to the previous fragment, but the order is acting strange. What exactly should I do to make the order proper?
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft){
if(teamsFrag !=null)
{
if(manage.getBackStackEntryCount() > 0)
manage.popBackStack(manage.getBackStackEntryAt(manage.getBackStackEntryCount()-1).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
//ft.detach(dataFrag);
}
Short answer? No.
Long answer? If you have to ask, No.
You should set your fragments up using the fragment manager so that the back button does what you want. You shouldn't override the back button instead of implementing your stack correctly.
I want to go back to the last fragment in the back stack, so I want to make the back button popback the stack.
This is the default behavior when you use FragmentTransaction#addToBackStack() while adding new Fragments with the FragmentManager.

Categories

Resources