2

The issue I'm noticing happens when the user scrolls to the next (or previous) page in the ViewPager, which triggers the ViewPager's settling (confirm?) to that page. This works perfectly unless the user starts dragging while the ViewPager is still settling. In this scenario what I get is the title shown by the TitlePageIndicator shows the title for 2 pages after (or before, respectively) while the content shown by the ViewPager is showing the next (or previous) page.

If the user starts to swipe after that page - the one with the mismatched title and content - has settled, the title gets quickly updated to the correct title. Looking at ViewPager.OnPageChangeListener they say "Useful for discovering when the user begins dragging, when the pager is automatically settling to the current page" for onPageScrollStateChanged(int), which seems to be what the issue is, but I haven't found a way to use the method to resolve the issue.

I'm using Jake Wharton's com.viewpagerindicator.TitlePageIndicator with android.support.v4.view.ViewPager to render a view of calendar days. Swiping left/right moves to the previous/next calendar day. This means my ViewPager is set up to implement infinite pagination based on 3 Fragments that correspond to the visible day, the day before the visible day, and the day after the visible day.

My ViewPager.OnPageChangeListener is constructed like this and attached to the TitlePageIndicator

_title.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        private int _focused_page = _VISIBLE;
        private boolean _is_settling = false;

        @Override
        public void onPageScrollStateChanged(int state) {
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                if (_focused_page == _PREVIOUS)
                    moveToPrevious();
                else if (_focused_page == _NEXT)
                    moveToNext();

                // always set to middle page to continue to be able to
                // scroll left/right
                if (_paginator.getCurrentItem() != _VISIBLE)
                    _paginator.setCurrentItem(_VISIBLE, false);
                _is_settling = false;
            } else if (state == ViewPager.SCROLL_STATE_DRAGGING && _is_settling) {
                Ln.d("Double scrolled!");
                _title.setCurrentItem(_paginator.getCurrentItem());
                _title.invalidate();
            } else if (state == ViewPager.SCROLL_STATE_SETTLING) {
                _is_settling = true;
            }
        }

        @Override
        public void onPageSelected(int position) {
            _focused_page = position;
        }
});

I see there to be about 3 solutions

  • Disable the sending or responding to user drag event while settling
  • Notice when the drag occurs during a settling and recover the correct title after it becomes invalid
  • Move the ViewPager with the second drag as if it were the first drag resulting in everything being 2 pages after (or before) the original visible day

EDIT: Is there a way to force the TitlePageIndicator to call getPageTitle(int) again to redraw the title with the correct title?

4

1 回答 1

1

感谢您的第一次实施,我找到了解决方案。

private static final int PAGE_LEFT = 0;
private static final int PAGE_MIDDLE = 1;
private static final int PAGE_RIGHT = 2;

mTitleIndicator.setOnPageChangeListener(new OnPageChangeListener() {
            private boolean isSettling;
            private int focusedPage = 1;

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                focusedPage = position;
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                if (sViewPager.getChildAt(PAGE_RIGHT) != null) {
                    if (state == ViewPager.SCROLL_STATE_IDLE) {

                        // User swiped in right direction, change to left page.
                        if (focusedPage == PAGE_LEFT) {
                            doSomething();

                            // User swiped in left direction, change to right page.
                        } else if (focusedPage == PAGE_RIGHT) {
                            doSomething();
                        }
                        mTitleIndicator.setCurrentItem(PAGE_MIDDLE, false);
                        isSettling = false;

                    } else if (state == ViewPager.SCROLL_STATE_DRAGGING && isSettling) {
                        mTitleIndicator.notifyDataSetChanged();

                    } else if (state == ViewPager.SCROLL_STATE_SETTLING) {
                        isSettling = true;
                    }
                } else {
                    mTitleIndicator.setCurrentItem(PAGE_MIDDLE, false);
                }
            }
        });

编辑:有没有办法强制 TitlePageIndicator 再次调用 getPageTitle(int) 以用正确的标题重绘标题?

是的,调用TitlePageIndicator.notifyDataSetChanged()(仅调用invalidate())。



编辑:我的解决方案仅在向后滚动时有效,而不是向前滚动。

于 2013-02-01T14:05:54.957 回答