I ran into this problem where my ListFragment is empty after having popBackStackImmediate
I have a main activity which extends FragmentActivity and I have a Navigation drawer attached with my main activity. The first navigation calls a Fragment which has a custom adapter which implements FragmentStatePagerAdapter showing three tabs. each of the tabs are ListFragments them selves. when i click on any row of the list it goes to another fragment, till this everything works fine, now I want to implement the backstack so that when user presses back button from the detail page they can come back to the FragmentList page again. when I press back button it takes me back to the FragmentList page that is fine but the page is empty, for some reason the list does not shows up. I've checked the log and found the data is there and it goes till last bit of the code with out any error but the page is empty, can any one help me with that?
When I select any item from the List of any tab I add the transaction into the backstack and move on to detail fragment:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Fragment fragment = new LiveMatchDetailMainFragment();
android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack("LiveFragment");
fragmentTransaction.commit();
}
In my main activity I have this:
#Override
public void onBackPressed(){
Log.d("stack","back pressed");
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0)
{
//fm.popBackStack();
boolean done = fm.popBackStackImmediate();
Log.i("stack", String.valueOf(done));
} else
{
Log.i("stack", "nothing on backstack, calling super");
super.onBackPressed();
}
}
which takes me to exact tab where I clicked the item from the list, but only problem is the fragment is empty.
In the FragmentList page I have:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
LiveMatchList = new ArrayList<HashMap<String, Object>>();
//Log.d("LiveMatchList setUserVisibleHint","setUserVisibleHint");
new LoadUpcomingMatchList().execute();
}
}
which creates a list using custom adapter, and it works fine for the first time, when I pop the backstack this method gets call and loads all the data comes down till onPostExecute but the list is never showed, sorry guys I am not new to stackoverflow but this is my second question post so I might not follow the convention correctly...
Apparently with some help I fixed the issue...
I added the fragment transactions within the FragmentActivity and used my onListItemClick() callback method to call a FragmentActivity method, which should run the transaction.
In EventFragment replaced:
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
viewpager.setAdapter(new MyAdapter(fragmentManager));
with:
viewpager.setAdapter(new MyAdapter(getChildFragmentManager()));
it was the getChildFragmentManager() that solved my problem mainly.
Related
I have a bottom bar with diferent tabs. When one is pressed a fragment should start. Im trying implement backStack on my project. The objective is, when i press a diferent tab, the fragment will be poped from backstack or created if does not exist.
void cretePeopleFrgament() {
boolean fragmentPopped = fragmentManager.popBackStackImmediate("Users", 0);
if (!fragmentPopped) { //fragment not in back stack, create it.
FragmentTransaction ft = fragmentManager.beginTransaction();
Fragment fraggy = new FragmentAllPeople();
ft.addToBackStack("Users");
ft.replace(R.id.conteiner, fraggy);
ft.commit();
}
setDrawerEnabled(false);
}
with this im trying to evitate conections to server
#Override
public void onStart() {
super.onStart();
Http conections(...)
}
the problem is that both oneĀ“s, popBackStackImmediate and Fragment fraggy = new FragmentAllPeople(); pass form the method on Start. How can i evitate these conections?
Switch to using a ViewPager with Fragments (and tabs). The FragmentStatePagerAdapter will do the backstack popping automatically for you then.
I have this Activity in which I replace the main fragment with a preference fragment. When I click back after looking at the preferences, I get a blank (white) area where my fragment should be. If I rotate the screen then it works just fine. Everything in my fragment appears to be ok except for it is blank. Here are my methods:
The onCreate method of the activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
.....
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(MAIN_CONTAINER, new MainFragment())
.commit();
}
}
The starting of the preferences fragment:
public void startPreferencesFragment() {
FragmentManager mFragmentManager = getFragmentManager();
FragmentTransaction mFragmentTransaction = mFragmentManager
.beginTransaction();
MyPreferencesFragment mPrefsFragment = new MyPreferencesFragment();
mFragmentTransaction.addToBackStack(null)
.replace(MAIN_CONTAINER, mPrefsFragment)
.commit();
}
The onBackPressed of my activity:
#Override
public void onBackPressed() {
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
return;
}else {
super.onBackPressed();
}
}
So what am I doing wrong?
Thanks.
EDIT: If I open preferences and then rotate and then press back, it all works fine.
Also I should mention that removing the onBackPressed method does not fix the issue, it just exits the app.
EDIT: Turned out to not be a problem with the fragment back stack at all. Basically my fragment has a recyclerview and that is all it has. The instance of the adapter I was setting on the recyclerview was being kept while the recyclerview itself was new when the fragment was brought back from the back stack and I was checking whether the adapter was null when setting it.
You are already adding the transaction to the backstack, there is not need to override onBackPressed(); the framework will pop the Fragment out of the stack automatically when the back button is pressed. I am pretty sure that you are "double" popping the backstack.
I'am working on a Product Detail page that opens every time the user clicks on a product on a list. In the page i have some product image at the top, and then 3 tabs below the image, and a fragment container below the tab to switch between the tabs.
The Problem: First time i load the Activity i call the showFragment(..) method, and it populate the fragment_container with the InfoFragment. When i then click on another tab and call the showFragment() method again, the container becomes blank. The funny thing is that when i go back to the list and click the same product again, it loads the infoFragment in the container as before, but when i click on the tabs they switch like butter (without problems).. Anyone have an idea of what is going wrong??
This is the method i call in onCreate() that shows the infoFragment at start:
showFragment(R.id.product_detail_fragment_container, mInfoFragment, INFO_TAG, mCurrentFragmentTag, false);
When i click on a different (2nd) tab i call the same method with different parameters:
showFragment(R.id.product_detail_fragment_container, mCaraFragment, CARA_TAG, mCurrentFragmentTag, false);
And the showFragment(...) method:
protected void showFragment(int resId, Fragment fragment, String tag, String lastTag, boolean addToBackStack)
{
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (lastTag != null) {
Fragment lastFragment = fragmentManager.findFragmentByTag(lastTag);
if (lastFragment != null) {
transaction.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
transaction.hide(lastFragment);
}
}
if (fragment.isAdded()) {
transaction.show(fragment);
} else {
transaction.add(resId, fragment, tag).setBreadCrumbShortTitle(tag);
}
if (addToBackStack) {
transaction.addToBackStack(tag);
}
transaction.commit();
}
XML for the container:
<FrameLayout
android:id="#+id/product_detail_fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white" />
I have tried debugging the code, and it calls the transaction.add(resId, fragment, tag) method when i switch tab, but the container becomes blank. Then i close and start the detail page again, the method gets called and it shows the content... When i then try with another product it wont show the fragment, until i go back and click on it again
My app has tabs and within one tab, I have a Fragment with a ListView. When an item is clicked in the list, I try to initialize a new Fragment under that tab with the following:
private class ShowItemClickListener implements OnClickListener {
public void onClick(View v) {
Fragment showDetails = new ShowFragment();
FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, showDetails);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
System.out.println(activity.getFragmentManager().getBackStackEntryCount()); // this prints 0 though
}
}
As a result, when I press the back button in Show Fragment view, it just closes the application instead of returning to the previous fragment. What am I doing wrong here?
Sorry for late answer but maybe somebody will have same question.
I was solving the same problem. It seems actual fragment is added to backstack only if this fragment isn't in current view. So it will be added to stack after when you switch to next fragment.
I'm working with Fragments for the first time and running into a weird behavior. I have an activity with a Fragment covering the entire view. It contains a ListView. When I tap on an item in the ListView, I want to show a details fragment which contains information about that item.
This is how I'm presenting the new fragment view:
FragmentManager fragmentManager = this.getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
DetailsFragment fragment = new DetailsFragment();
transaction.add(R.id.viewRoot, fragment).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack("Details").commit();
R.id.viewRoot is the id of the root layout in the first Fragment's layout xml, so the new Fragment fills the entire screen.
My Problem: When the new fragment is visible and covering the entire screen, any clicks or taps which land on the background (i.e. not hitting a button or textfield on the new fragment) appear to be going through the view and landing on the first fragment. So, I tap on a ListView item, which causes the DetailsFragment to get added to the screen. Then when I tap on the background of the DetailsFragment, that tap falls through and lands on the ListView causing another DetailsFragment to be added for whatever item I happened to hit behind the scenes.
Am I adding my new fragment incorrectly? Why are my clicks/taps falling through?
EDIT for caiuspb:
public class BaseFragment extends Fragment {
public void pushNewFragment(Fragment fragment, String description) {
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.remove(this);
transaction.add(R.id.viewRoot, fragment).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack(description).commit();
}
}
All of my fragments extend my BaseFragment class.
I experimented with the suggestions I received, but none of them worked. In the end, my solution was to add an OnTouchListener to the root view of my subfragments which discarded all touches.
View view = inflater.inflate(R.layout.mylayout, container, false);
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
There is another post here on StackOverflow about that strange Fragment behaviour. Try to remove your Fragment before you add it because the replace Method seems to be buggy
edit:
Move the Fragment logic into your Activity because your activity contains your Fragments. Today I tried to use the FragmentActivity and Fragments from the Android Support Library. Now I can use the replace method withouht any bugs. This is my approach and this works:
public class DashActivity extends FragmentActivity{
...
private void changeRightFragment(Fragment fragment) {
Log.i(TAG, "Loading Fragment into container: " + fragment.getClass().toString());
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.rightfrag, fragment);
// Add a transition effect
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// Add the Fragment to the BackStack so it can be restored by
// pressing the Back button
ft.addToBackStack(null);
ft.commit();
}
...
public void setUserFragment(User user) {
UserFragment fragment = new UserFragment(user);
changeRightFragment(fragment);
}
So if you want to invoke a changeFragment method from inside your Fragment use a callback mechanism to the Activity