0

I have a set of vertically scrollable pages used in ViewPager. I need to retain the state of each ScrollView to preserve the scroll position. Setting mPager.setOffscreenPageLimit() to the maximum number of pages works correctly, but takes too long to load. What I need is for ViewPager to invoke onCreateView() lazily when it needs to, but not destroy any views that have already been created. One solution that seems to work just right is to override FragmentPagerAdapter.destroyItem() and do nothing in there, don't call super.

Question: will this cause any problems? Is there a better way to do this? TIA.

static ArrayList<ScreenSlidePageFragment> fragments;

public void onCreate(Bundle savedInstanceState) {
    ...
    fragments = new ArrayList<ScreenSlidePageFragment>();
    for (int i = 0; i < numScrollViews; ++i) {
        ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
        fragment.initialize(Integer.toString(i));
        fragments.add(fragment);
    }

    ViewPager mPager = (ViewPager) findViewById(R.id.viewpager);
    PagerAdapter mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager());
    mPager.setAdapter(mPagerAdapter);
    // adding the following line makes things slow
    //mPager.setOffscreenPageLimit(fragments.size());
    ...
}

public static class PagerAdapter extends FragmentPagerAdapter {
    public PagerAdapter(FragmentManager fm) {    // Must define an explicit constructor
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        System.out.println("PagerAdapter: getItem "+position);
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        System.out.println("PagerAdapter: destroyItem "+position);
        // do not call super.destroyItem(container, position, object)
    }
}

public static class ScreenSlidePageFragment extends Fragment {
    private String mKey;

    public ScreenSlidePageFragment() {
        System.out.println("ScreenSlidePageFragment: constructor ");
    }

    public void initialize(String key) {
        mKey = key;        // instead of args Bundle BS
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout containing a title and body text.
        ViewGroup rootView = (ViewGroup) inflater
                .inflate(R.layout.fragment_screen_slide_page, container, false);

        TextView textView = (TextView) rootView.findViewById(android.R.id.text1);
        textView.setText("Key "+mKey);

        textView = (TextView) rootView.findViewById(android.R.id.text2);
        textView.setText("blah blah");
        System.out.println("ScreenSlidePageFragment: onCreateView: "+mKey);
        return rootView;
    }
}

2 Answers 2

1

FragmentStatePagerAdapter is what you are looking for

The normal FragmentPagerAdapter does not recreate the complete Fragment, but only releases the view to save memory. FragmentStatePagerAdapter instead will destroy the complete Fragement if you swipe along the viewpager .

So in your case you could use FragmentStatePagerAdapter and override the Fragments onSaveInstanceState(Bundle outState) where you store the current scroll position. Then restore the scroll position in onCreateView(Bundle savedInstanceState).

Sign up to request clarification or add additional context in comments.

2 Comments

Cool. onSaveInstanceState seems to work. But my hack seems to work well too, except for the fact that it is undocumented :-(
@SoloPilot I used the same hack as well and found that it worked well on the devices that I tested with (medium to high end)
0

Output from the embedded print statements indicates that onCreateView() is not called repeatedly for the same ScrollView page.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.