I'm working on a application which has Single activity rest all fragments...
This issue i'm facing occurs occasionally.. like when ever i press back button from any of the fragment the previous fragment appears... but sometimes it happens that My activity shows blank screen with action bar present, and rest of the screen is blank instead of showing the fragment... Since this issue appears occasionally i'm not able to debug it also... Any idea why it happens so??
Here is the code fragment transaction..
private void loadFragment(Fragment fragment, int activityNumber) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction trnx = manager.beginTransaction();
trnx.replace(R.id.fragPage, fragment, "Current_Fragment");
if (activityNumber != FragmentActivityNumbers.HOME_ORDERNUM) {
trnx.addToBackStack(null);
}
trnx.commit();
}
I suggest to test if its the first fragment so you use Add instead of replace then you can use replace for the others fragments .
Related
I upgraded my app from SDK 26 to SDK 28 and it ruined my app's navigation. I have a central tabbed activity. In each tab, the flow of the app is managed by fragments. I have implemented the back press in a way that the previous fragment of the current tab is shown. The back press code is:
public void onBackPressed() {
String name = fragmentManager.getBackStackEntryAt(
fragmentManager.getBackStackEntryCount() - 1).getName();
Fragment fragment = fragmentManager.findFragmentByTag(name);
String tag = ((AppFragment) fragment).getPreceddingFragmentTag();
Fragment frag = fragmentManager.findFragmentByTag(tag);
removeFragment(fragment);
replaceFragment(frag, tag);
}
I pass the current fragment's tag to the next in its constructor which is then fetched by the getPreceddingFragmentTag() method in the above code.
I use one method to show new fragments on the screen as well as remove them when back is pressed. Here's the code for that:
private void replaceFragment(Fragment fragment, String tag) {
loadedFragment = (AppFragment) fragment;
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(mContainerId, fragment, tag);
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commit();
invalidateOptionsMenu();
}
I maintain the backstack to keep track of transactions and get the currently displayed fragment when the user presses back.
The remove fragment method is:
private void removeFragment(Fragment fragment) {
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
}
My app works in the following manner:
The tab opens up a fragment that contains a list that takes the user to the next fragment upon item click; which is also a list, tapping on an item in the list takes the user to the item's detail fragment.
Here's the issue:
I go from the first fragment to the next, then to the item details and come back. It works perfectly the first time.
I tap on another item on the list in the first fragment, it shows the next fragment perfectly, I tap on an item for details and then press back. Instead of showing the fragment that it was supposed to show, it shows the fragment that was shown in the previous flow.
I have ruined days and nights on stackoverflow, medium and Google Developers Documentation and have found no solution. My app was working perfectly with SDK 26 and 28 ruined everything. Can anyone help?
Same issue happened with me as well. In my case this issue happened due to following library:
androidx.appcompat:appcompat:1.1.0
Downgrade this library to androidx.appcompat:appcompat:1.0.0. This probably will fix your transaction issue. I am not sure if this is bug in library or they made any sort of improvement as i haven't found any particular notes in appcompat:1.1.0 release notes.
The scenario is this...I click on a button that loads the next fragment. While the animation is still going I hit the recent apps button. After the recent apps screen is shown i return to my app.
Then I see the two fragments drawn on top of each other. As if Android forgot to remove the previous fragment.
I click back to remove all fragments until I reach the first fragment loaded in this FragmentActivity. I log all the fragments I get from FragmentManager and it only shows one. But I still see two fragments drawn one on top of the other. The one that should have been removed is not responding to touch events and the other one responds as it should.
Is this an Android bug or my fault? Is there any way to fix this or prevent it from happening ?
It does not happen every time. This is how I load my fragments
public void loadNewFragment(AnimFragment newFragment, boolean addToSTack, boolean animate, String tag) {
if (newFragment != null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.fragment_enter_from_right, R.anim.fragment_exit_to_left, R.anim.fragment_enter_from_left, R.anim.fragment_exit_to_right);
transaction.replace(R.id.fragment_container, newFragment, tag);
if (addToSTack) {
transaction.addToBackStack(tag);
}
int transactionId = transaction.commit();
newFragment.setTransactionId(transactionId);
}
}
and I remove them on back pressed with
getSupportFragmentManager().popBackStackImmediate();
In my opinion "below" fragment is onPause() state and it's still alive and visible.
Try to use white background on the root layout of the front fragment to avoid showing the below fragment. Moreover the root layout size (width and height) of the front fragment should be match_parent.
Check this site to understand Fragment lifecycle.
https://google-developer-training.gitbooks.io/android-developer-advanced-course-concepts/unit-1-expand-the-user-experience/lesson-1-fragments/1-2-c-fragment-lifecycle-and-communications/1-2-c-fragment-lifecycle-and-communications.html
Basically, I want to open a fragment from Activity. Everything worked fine (activity button opens the fragment and the fragment shows), until I miss-clicked outside the fragment's layout where one of the Activity button is located and it did its onClick method. That's why I wondered why is my Activity still active.
this is how I open the fragment from Activity
I tried using .add instead of .replace still the same.
#OnClick(R.id.login_register_lbl)
public void registerAction(View view) {
// TODO register transition...
FragmentManager fragmentManager = (LoginActivity.this.getFragmentManager());
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
RegisterFragment fragment = new RegisterFragment();
fragmentTransaction.replace(R.id.fragment_register_holder, fragment);
fragmentTransaction.commit();
}
In fragment layout in root element set "background" , "clickable=true" & Focusable="true".
In my opinion you can achieve this functionality by 2 ways:
Open a dialog fragment in full screen mode to avoid accidentally clicks on activities views.
If you wanted to show both fragment's and activity's views at the same time then, on click of your activity's button which opens the fragment, disable it by yourbutton.setenabled(false); and when you wanted to close the fragment enable that button again.
I read many threads to this topic but nothing could help me.
I can´t post my code, but i try to explain my situation:
I´m getting an IllegalStateException: can not perform this action after onSaveInstanceState
I have an activity Main (with an DrawerLayout / navigation drawer). In this activity is always 1 fragment. At first there is the fragment WelcomePage.
When the user clicks the fragment gets replaced with new fragment (I call it: FootballClubs). This fragment contains a ViewPager, so it consists of multi pages; each page is a fragment FootballClub. (So the fragment FootballClubs consists of multi pages of one FootballClub fragment). In each FootballClub fragment is a button where the user can click; on click opens a new fragment (I call it NewFragment).
At first, everything is ok and no exception is thrown. I can click the button as often as possible, each time the new fragment is shown correctly without an exception, and onBackPressed I get back to FootballClubs with the ViewPager. But when I turn my smartphone, screen orientation has changed at least one time, I get following exception when I click on the button to open the new fragment (whatever fragment I want to show):
IllegalStateException: can not perform this action after onSaveInstanceState
I replace the fragments WelcomePage/FootballClubs/NewFragment with this code:
protected void replaceSubfragment(int containerID, Fragment newFragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(containerID, newFragment);
transaction.commit();
}
The exception is thrown in transaction.commit();
containerID is always the same (FrameLayout in activity layout)
Some additional information:
If I replace
transaction.commit();
with
transaction.commitAllowingStateLoss();
I get this Exception: IllegalStateException: Activity has been destroyed (although I click/do exactly the same)
All fragments gets replaced in my FragmentActivity class Main; When you click on the button, the Subclass of SectionPage gets noticed and calls a listener from FragmentActivity, so that the FragmentActivity can replace the fragments (BaseActivity gives the listener over to FootballClubs fragment, and this gives it over to the Subclass of SectionPage)
Due to the fact that I only replace fragments in my FragmentActivity I don´t use getChildFragmentManager(); (As far as I can remember this didn´t work too)
I know that the activity gets destroyed and recreated by the system when orientation changed, but I can´t do something with this information.. the whole app works perfectly except this button
If I want to show a dialog instead of NewFragment on button click I get an IllegalStateException too
In my FragmentActivity, I have a variable activeModule; here I can check activeModule.isAdded(); When the exception is thrown, isAdded() return false.. So I can check if the error will be thrown or not
I hope I could describe my problem. The screen orientation ruins everything, don´t know why..
If you need further information ask me.. if you need some code pieces maybe I can post something.
Thanks!
When I start my app it runs an AsyncTask to load up and then in onPostExecute, I then setContentView to the new layout then add a fragment with two buttons offering two modes by an add FragmentTransaction. After one of the two modes is clicked, it then replaces the fragment with yet another FragmentTransaction using the replace method.
If the app crashes it returns to the first screen, loading up the two buttons offering the two modes. In this case if either mode is selected, the second fragment is loaded but is now the background is suddenly transparent showing the two buttons below and they remain clickable. If they are clicked again they properly replace the fragment so that it isn't visible below. This is just weird, I can't understand what could cause this.
I've researched and seen these two similar questions, one and two, which suggested that it might be because the ID is wrong or I have defined the fragment in XML. Neither of these two factors are the case.
My code is shown below:
Below I replace the loading screen.
#Override
protected void onPostExecute(Void result) {
setContentView(R.layout.activity_main_screen);
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.add(R.id.fragment_container, new ModeFragment())
.commit();
}
After which, when a button is clicked I pass the fragment I wish to replace the current with into this method below:
private void replaceCurrentFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment_container, fragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack(null).commit();
}
This works the first time, however if a crash occurs then the app returns to the first fragment and the second time this method is passed, the new replacing fragment is semi-invisible. Clicking the button on the first fragment again calls this method again and it is now fine.
Obviously I don't want the app to crash so this shouldn't occur, but I get this feeling that there's something wrong with how I'm writing my code.
I've had the same problem happen to me, and it was because I loaded a fragment in the OnCreate of my Activity, without checking if there was a savedInstanceState, so android first reopen all old fragments, then do the OnCreate, which added the fragment over the old ones without replacing them so when you navigate to another fragment, it only replaces the top one, but not the bottom one, so you will see the fragments under it.
Might not be exactly the same thing for you, but it might help you figure it out.