-1

This is the situation. I have a listview in a fragment A with an infinite list that is populated throught web service when user reach bottom.

Each item in the listview have a "View more" link that open a detailed fragment B for this item.

I'm using FragmentManager.replace() method and "addToBackStack". (I'm "replacing" and not "adding" because I have menu items in fragment A that I don't want to show in fragment B. I already tryed different ways with adding fragment instead removing and trying to hide menu items when opening fragment B that have worked, but ended in some other problems, so I prefer to use replace")

Supose that user is seeing item 25 in the list and then open detail fragment. When the user then hit the back button, I want the user to continues viewing the list in the same position exactly.

This was easy to make with "adding fragment" instead of "replacing" because the fragment was never removed. When using "replace" the fragment is removed and then when hit back it will render again (aka, will call onCreateView again)

But at this point, the view is already created for the fragment because FragmentManager.remove only remove view from the view hierarchy, but don't destroy the fragment. So I "theoretically" can do something like this:

if(view == null){
    //Create view
    view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
}
return view;

But in this case it will result in an

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

So, my solution was the following:

if(view == null){
    view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
} else {
    ((ViewGroup) view.getParent()).removeView(view);
}
return view;

This is working for me, but I don't know if there will be some "hidden" errors beyond this solution that I'm not seeing right now.

I want to hear for your advices. Thanks in advance

edrian
  • 4,501
  • 5
  • 31
  • 35
  • possible duplicate of [Fragment - should I reuse view in onCreateView and how should I do that?](http://stackoverflow.com/questions/18637134/fragment-should-i-reuse-view-in-oncreateview-and-how-should-i-do-that) – Steve Benett May 07 '14 at 14:14
  • @SteveBenett I saw that question, and I also gave my answer to that question worked for me. But what I'm asking now, in this NEW question, is if the solution was OK or not. I have this solution on my own project, working, but I need someone to tell me if this solution may cause some other conflict that I'm not seeing – edrian May 07 '14 at 14:49

2 Answers2

0

Why not remember the position till where the user has scrolled in onPause of the fragment and set the list view position to the scrolled position in onResume? Just a thought, I am not sure if your solution has any adverse effects/errors.

  @Override
  public void onPause() {
    // TODO Auto-generated method stub
    super.onPause();

   try{
         index = this.getListView().getFirstVisiblePosition();
         View v = this.getListView().getChildAt(0);
         top = (v == null) ? 0 : v.getTop();
      }
      catch(Throwable t){
         t.printStackTrace();
      }

And in onResume of the fragment :

   @Override
public void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    /**
     *  Check to see if there is any scroll position
     *  saved up, this is done in case of user returning 
     *  back from the contact detail screen
     */
    setListAdapter(adapter);
      if(index!=-1){
         this.getListView().setSelectionFromTop(index, top);
      }
}

Hope this helps !

Adnan Mulla
  • 2,872
  • 3
  • 25
  • 35
  • 1
    Thanks!, I'll use this aproach but only if someone tell me that reusing the view in the way I've posted is wrong – edrian May 07 '14 at 14:52
0

If you do not call addToBackStack() when you perform a transaction that removes a fragment, then that fragment is destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you do call addToBackStack() when removing a fragment, then the fragment is stopped and will be resumed if the user navigates back.

Tip: For each fragment transaction, you can apply a transition animation, by calling setTransition() before you commit.

Calling commit() does not perform the transaction immediately. Rather, it schedules it to run on the activity's UI thread (the "main" thread) as soon as the thread is able to do so. If necessary, however, you may call executePendingTransactions() from your UI thread to immediately execute transactions submitted by commit(). Doing so is usually not necessary unless the transaction is a dependency for jobs in other threads.