From eb1e8d6e8b3462938e7b61d923ad608a7bcebb40 Mon Sep 17 00:00:00 2001 From: Timothy Johnson <_c_@mail.com> Date: Wed, 16 Jul 2014 10:17:26 -0700 Subject: [PATCH 1/2] Correctly handle non-visible views. --- .../horizontalpager/HorizontalPager.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/com/github/ysamlan/horizontalpager/HorizontalPager.java b/src/com/github/ysamlan/horizontalpager/HorizontalPager.java index 0ccc6cf..aa2ff92 100644 --- a/src/com/github/ysamlan/horizontalpager/HorizontalPager.java +++ b/src/com/github/ysamlan/horizontalpager/HorizontalPager.java @@ -138,6 +138,15 @@ private void init() { mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); } + public int getVisibleCount () { + int count = 0; + for (int i = 0; i < super.getChildCount(); i++) + if (getChildAt(i).getVisibility() != View.GONE) + count++; + + return count; + } + @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -175,7 +184,7 @@ else if (width != mLastSeenLayoutWidth) { // Width has changed .getDefaultDisplay(); int displayWidth = display.getWidth(); - mNextScreen = Math.max(0, Math.min(getCurrentScreen(), getChildCount() - 1)); + mNextScreen = Math.max(0, Math.min(getCurrentScreen(), getVisibleCount() - 1)); final int newX = mNextScreen * displayWidth; final int delta = newX - getScrollX(); @@ -351,7 +360,7 @@ public boolean onTouchEvent(final MotionEvent ev) { // Fling hard enough to move left snapToScreen(mCurrentScreen - 1); } else if (velocityX < -mDensityAdjustedSnapVelocity - && mCurrentScreen < getChildCount() - 1) { + && mCurrentScreen < getVisibleCount() - 1) { // Fling hard enough to move right snapToScreen(mCurrentScreen + 1); } else { @@ -383,7 +392,7 @@ public void computeScroll() { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } else if (mNextScreen != INVALID_SCREEN) { - mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1)); + mCurrentScreen = Math.max(0, Math.min(mNextScreen, getVisibleCount() - 1)); // Notify observer about screen change if (mOnScreenSwitchListener != null) { @@ -410,7 +419,7 @@ public int getCurrentScreen() { * @param animate True to smoothly scroll to the screen, false to snap instantly */ public void setCurrentScreen(final int currentScreen, final boolean animate) { - mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1)); + mCurrentScreen = Math.max(0, Math.min(currentScreen, getVisibleCount() - 1)); if (animate) { snapToScreen(currentScreen, ANIMATION_SCREEN_SET_DURATION_MILLIS); } else { @@ -443,7 +452,7 @@ private void snapToDestination() { && ((screenWidth / FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE) < -deltaX)) { whichScreen--; // Check if they want to go to the next screen - } else if ((deltaX > 0) && (mCurrentScreen + 1 != getChildCount()) + } else if ((deltaX > 0) && (mCurrentScreen + 1 != getVisibleCount()) && ((screenWidth / FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE) < deltaX)) { whichScreen++; } @@ -475,7 +484,7 @@ private void snapToScreen(final int whichScreen, final int duration) { * RadioGroup used as "tabbed" controls. Also, make the animation take a percentage of our * normal animation time, depending how far they've already scrolled. */ - mNextScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); + mNextScreen = Math.max(0, Math.min(whichScreen, getVisibleCount() - 1)); final int newX = mNextScreen * getWidth(); final int delta = newX - getScrollX(); From 6af96bb3ca41bd35a82fb0e854bef661d5ea6ef9 Mon Sep 17 00:00:00 2001 From: Timothy Johnson <_c_@mail.com> Date: Wed, 16 Jul 2014 10:21:54 -0700 Subject: [PATCH 2/2] Modified OnScreenSwitchListener to notify used before as well as after animation. --- .../ysamlan/horizontalpager/HorizontalPager.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/com/github/ysamlan/horizontalpager/HorizontalPager.java b/src/com/github/ysamlan/horizontalpager/HorizontalPager.java index aa2ff92..53f5c80 100644 --- a/src/com/github/ysamlan/horizontalpager/HorizontalPager.java +++ b/src/com/github/ysamlan/horizontalpager/HorizontalPager.java @@ -391,6 +391,12 @@ public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); + + // Notify observer about screen change + if (mOnScreenSwitchListener != null) { + int switchingScreen = Math.max(0, Math.min(mNextScreen, getVisibleCount() - 1)); + mOnScreenSwitchListener.onScreenSelected(switchingScreen); + } } else if (mNextScreen != INVALID_SCREEN) { mCurrentScreen = Math.max(0, Math.min(mNextScreen, getVisibleCount() - 1)); @@ -503,6 +509,13 @@ private void snapToScreen(final int whichScreen, final int duration) { * Listener for the event that the HorizontalPager switches to a new view. */ public static interface OnScreenSwitchListener { + /** + * Notifies listeners about the new screen. Runs before the animation completed. + * + * @param screen The new screen index. + */ + void onScreenSelected(int screen); + /** * Notifies listeners about the new screen. Runs after the animation completed. *