문제

I have an app whose main navigation feature is a ViewPager with essentially infinite pages. I'm using something similar to InfiniteViewPager (with a FragmentStatePagerAdapter), starting navigation in the middle of the ViewPager so there are pages to the left and right to start. I'm also using negative margins mPager.setPageMargin(-50); to have the pages on either side slightly visible.

I'm loading lots of data from the web, so I'm handling configuration changes myself by using android:configChanges="orientation|keyboardHidden" and the onConfigurationChanged override in my activity. Mainly, I don't want to recreate my Activity because I think it would take much too long when changing orientation.

Problem

I open the app, swipe in either direction, wait for the ViewPager to stop animating, then change orientation. The current page is now slightly off center and one neighboring page is more exposed than the other. Sometimes one of the neighboring pages is completely offscreen.

If I touch the page, the ViewPager scroll to the current page and displays as expected, but unless I do that, the display is wrong. I get this problem going from Landscape to Portrait and Portrait to Landscape. I've tried setting a OnGlobalLayoutListener and performing mViewPager.setCurrentItem(mViewPager.getCurrentItem()) but ViewPager ignores setCurrentItem if you ask it to set the current item to what is actually the current item.

Code

MainActivity

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //whatever I do in here doesn't make a difference.
    //my viewpager still displays off center, even if I do nothing custom
}

Pager Adapter

private class MyAdapter extends FragmentStatePagerAdapter{

    public CarouselPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        PageData dataForThisPage = mModel.getDataForPage(position);
        PageContainerFragment f = PageContainerFragment.create(position, dataForThisPage);

        return f;
    }

    @Override
    public int getCount() {
        return 2000;
    }
}

I've been trying to figure this out for hours and I can't get anywhere. Any help would be greatly appreciated!

Edit: styling

도움이 되었습니까?

해결책

I found the answer to my problem here: https://code.google.com/p/android/issues/detail?id=39287. Size changes don't play nicely with ViewPagers that have a non-zero margin, so the work-around solution is to extend ViewPager and add the following Override method.

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w-this.getPageMargin(), h, oldw-this.getPageMargin(), oldh);
}

다른 팁

onConfigurationChanged is not called when you change orientation because you haven't marked orientation in manifest. This method should be override ONLY when you are planning to manually handle orientation changes.

Methods you should take look at are: http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)

and

http://developer.android.com/reference/android/app/Activity.html#onRestoreInstanceState(android.os.Bundle)

First one is called before activity is destroyed (what happens when you change configuration) Second one is called when activity is recreated, so you need pass params you need (i.e. current page of view pager) in the first one, read it in second one and manually restore state of your view / adapter etc.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top