Nouman Bhatti
Nouman Bhatti

Reputation: 1837

Maintain fragment's view state

I have seen Link1 for this issue but could understand it right. I have a fragment that loads a list. When i click the list item it opens another activity. But i press back button it loads the list again. I want it to be at the same scroll position where it was before. In above mentioned link it specifies to use flag but i haven't got the point.

public class MainActivity extends Activity { 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_dashboard); 
    android.app.Fragment fragment = new MeFragment();    
    getFragmentManager().beginTransaction().replace(R.id.layout_FragmentsContainer, fragment).addToBackStack(null).commit();
   }
}

public class MeFragment extends Fragment
{
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  
  {
    return inflater.inflate(R.layout.fragment_me, container, false);
  }
  @Override
  public void onActivityCreated(Bundle savedInstanceState) {  
    super.onActivityCreated(savedInstanceState);

    meLV = (ListView) getView().findViewById(R.id.lv_Inbox);
    loadingListProgress = (ProgressBar) getView().findViewById(R.id.progress_LoadingList);  
    meList = new ArrayList<Message>();
    meAdapter = new MessagesListAdapter(getActivity(), meList);  
    //addFooter();
    meLV.setAdapter(meAdapter);
    meLV.setOnItemClickListener(this); 
    pageCount = 0;
    loadmoreProgressDialog = new ProgressDialog(getActivity()); 
    loadmoreProgressDialog.setTitle("Please wait ..."); 
    loadmoreProgressDialog.setMessage("Loading more ...");  
    loadmoreProgressDialog.setCancelable(true);
    loadUserMessages(); 
    meLV.setOnScrollListener(new EndlessScrollListener() {
        @Override
        public void onLoadMore(int page, int totalItemsCount) {
            // TODO Auto-generated method stub
            //addFooter();
            loadmoreProgressDialog.show();
            loadUserMessages();
        }
    }); 
  }  
  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
    // TODO Auto-generated method stub
    Utils.showToast_msg(getActivity(), "MessageItemClicked"); 
    ReferralDetailFragment fragment = new ReferralDetailFragment();    
    getFragmentManager().beginTransaction().replace(R.id.layout_FragmentsContainer, fragment).addToBackStack(null).commit();

  }
} 

public class ReferralDetailFragment extends Fragment implements OnClickListener {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  
{
    View view = inflater.inflate(R.layout.fragment_referraldetail,container, false);
    linkToAcknowledge   = (TextView) view.findViewById(R.id.lbl_Link_to_Acknowledge);
    return view;  
  }
}

Upvotes: 1

Views: 247

Answers (3)

Manish
Manish

Reputation: 1279

What you are trying to achieve may be done with help of savedInstanceState. i also had this kind of problem which i resolved by using add() method instead of replace() in transition. If you can change your method or already not using add() than give it a shot. and if add() method didn't do the trick then check the implementation of savedInstanceState.

  1. correctly save instance state.

  2. How to save states of fragment views.

Upvotes: 0

HpTerm
HpTerm

Reputation: 8281

According to our exchange in the comments, I completely deletde my answer and re-write a new one.

I copy/paste the code from one of my apps and removing the useless things and changing the names. Hope there is not too many typing mistakes, at that it is the minimum required to have it working.

When I pop back to FirstFragment from SecondFragment, the scroll position of FirstFragment is the same as when I clicked an item to load the SecondFragment.

Note that I don't extend FragmentActivity. I have an activity which loads the fragments.

Extend/modify to match your needs.

MainActivity :

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);
    }
}

FirstFragment Class :

public class FirstFragment extends Fragment implements OnItemClickListener {
    private ListView mListView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.first_fragment_layout, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mListView = (ListView) getView().findViewById(R.id.listview_first_fragment);
        mListView.setAdapter(mAdapter); // depends on your adapter
        mListView.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mListView.setItemChecked(position, true);

        //in case you need, set the bundle here, for example pass the position
        Bundle arguments = new Bundle();
        arguments.putInt("position", position);
        SecondFragment secondFragment = new SecondFragment();
        secondFragment.setArguments(arguments);

        getFragmentManager().beginTransaction().replace(R.id.fragment_container, secondFragment).addToBackStack(null).commit();
    }
}

SecondFragment Class :

public class SecondFragment extends Fragment {
    private Integer mPosition;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.second_fragment_layout, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        Bundle arguments = getArguments();
        if (arguments == null) {
            mPosition= 0;
        } else {
            mPosition= arguments.getInt("Position");
        }
    }
}

Upvotes: 1

Kartik_Koro
Kartik_Koro

Reputation: 1287

I implemented a simple solution for this in my app, basically when you press back to go to the fragment again, onCreateView() is called. Here in onCreateView() you have done all initialization, so we change

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  
{
    View view = inflater.inflate(R.layout.fragment_me, container, false);
    /*
     *Whatever you want to do
     *
     */
    return view;  
}

to:

View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  
{
    if(view==null){

        view = inflater.inflate(R.layout.fragment_me, container, false);
        /*
         *Whatever you want to do
         *
         */
    }
    else{
         ((ViewGroup)view.getParent()).removeView(view);
    }
    return view;  
}

Here, we move View view outside and make it a class variable. So if it is the first time the fragment is called, it is null and the initialization occurs, otherwise it goes to else black. Else block is required because onCreateView() adds whatever it returns as a child of the view's parent, so since view is already there, we remove it and onCreateView automatically adds it again.

Upvotes: 1

Related Questions