Android Open Source - Peterson Horizontal Pager






From Project

Back to project page Peterson.

License

The source code is released under:

GNU General Public License

If you think the Android project Peterson listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright (c) 2013 Zheng Sun.//w w  w.  jav  a2s .  c  o  m
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Zheng Sun - initial API and implementation
 ******************************************************************************/

package tv.huohua.peterson.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Scroller;

public final class HorizontalPager extends ViewGroup {
  private static final int ANIMATION_SCREEN_SET_DURATION_MILLIS = 500;
  private static final int FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE = 15;
  private static final int INVALID_SCREEN = -1;
  private static final int SNAP_VELOCITY_DIP_PER_SECOND = 600;
  private static final int VELOCITY_UNIT_PIXELS_PER_SECOND = 1000;

  private boolean isDragging;
  private HorizontalPagerListener listener;
  private int mCurrentScreen;
  private int mDensityAdjustedSnapVelocity;
  private boolean mFirstLayout = true;
  private float mLastMotionX;
  private float mLastMotionY;
  private int mLastSeenLayoutWidth = -1;
  private int mMaximumVelocity;
  private int mNextScreen = INVALID_SCREEN;
  private int mTouchSlop;
  private VelocityTracker mVelocityTracker;
  private Scroller scroller;

  public HorizontalPager(final Context context) {
    super(context);
    init();
  }

  public HorizontalPager(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  @Override
  public void computeScroll() {
    if (scroller.computeScrollOffset()) {
      scrollTo(scroller.getCurrX(), scroller.getCurrY());
      postInvalidate();
    } else if (mNextScreen != INVALID_SCREEN) {
      mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
      if (listener != null) {
        listener.onScreenSwitch(mCurrentScreen);
      }
      mNextScreen = INVALID_SCREEN;
    }
  }

  public int getCurrentScreen() {
    return mCurrentScreen;
  }

  public HorizontalPagerListener getListener() {
    return listener;
  }

  private void init() {
    this.scroller = new Scroller(getContext());
    this.isDragging = false;

    final DisplayMetrics displayMetrics = new DisplayMetrics();
    ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(
        displayMetrics);
    mDensityAdjustedSnapVelocity = (int) (displayMetrics.density * SNAP_VELOCITY_DIP_PER_SECOND);

    final ViewConfiguration configuration = ViewConfiguration.get(getContext());
    mTouchSlop = configuration.getScaledTouchSlop();
    mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
  }

  @Override
  public boolean onInterceptTouchEvent(final MotionEvent event) {
    final int action = event.getAction();
    final float x = event.getX();
    final float y = event.getY();

    switch (action) {
    case MotionEvent.ACTION_DOWN:
      mLastMotionX = x;
      mLastMotionY = y;
      break;
    case MotionEvent.ACTION_MOVE:
      if (!isDragging) {
        final int xDiff = (int) Math.abs(x - mLastMotionX);
        final int yDiff = (int) Math.abs(y - mLastMotionY);

        if (xDiff > mTouchSlop && yDiff > mTouchSlop) {
          isDragging = (xDiff >= yDiff);
        } else if (xDiff > mTouchSlop) {
          isDragging = true;
        } else if (yDiff > mTouchSlop) {
          isDragging = false;
        }
      }
      break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
      if (isDragging) {
        isDragging = false;
        snapToDestination();
      }
      break;
    default:
      break;
    }
    if (isDragging) {
      mLastMotionX = x;
      mLastMotionY = y;
    }
    return isDragging;
  }

  @Override
  protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
    int childLeft = 0;
    final int count = getChildCount();

    for (int i = 0; i < count; i++) {
      final View child = getChildAt(i);
      if (child.getVisibility() != View.GONE) {
        final int childWidth = child.getMeasuredWidth();
        child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
        childLeft += childWidth;
      }
    }
  }

  @Override
  protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    final int width = MeasureSpec.getSize(widthMeasureSpec);

    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
      getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
    }

    if (mFirstLayout) {
      scrollTo(mCurrentScreen * width, 0);
      if (listener != null) {
        listener.onScreenSwitch(mCurrentScreen);
      }
      mFirstLayout = false;
    } else if (width != mLastSeenLayoutWidth) {
      final Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
          .getDefaultDisplay();
      @SuppressWarnings("deprecation")
      final int displayWidth = display.getWidth();
      mNextScreen = Math.max(0, Math.min(getCurrentScreen(), getChildCount() - 1));
      final int newX = mNextScreen * displayWidth;
      final int delta = newX - getScrollX();
      scroller.startScroll(getScrollX(), 0, delta, 0, 0);
    }

    mLastSeenLayoutWidth = width;
  }

  @Override
  protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
    if (listener != null) {
      listener.onScrollChanged(l, t, oldl, oldt);
    }
    super.onScrollChanged(l, t, oldl, oldt);
  }

  @Override
  public boolean onTouchEvent(final MotionEvent event) {
    if (mVelocityTracker == null) {
      mVelocityTracker = VelocityTracker.obtain();
    }

    mVelocityTracker.addMovement(event);

    final int action = event.getAction();
    final float x = event.getX();
    final float y = event.getY();

    switch (action) {
    case MotionEvent.ACTION_DOWN:
      if (!scroller.isFinished()) {
        scroller.abortAnimation();
      }

      mLastMotionX = x;
      mLastMotionY = y;
      isDragging = true;
      break;
    case MotionEvent.ACTION_MOVE:
      final int xDiff = (int) Math.abs(x - mLastMotionX);
      if (xDiff > mTouchSlop) {
        isDragging = true;
      }

      if (isDragging) {
        final int deltaX = (int) (mLastMotionX - x);
        final int scrollX = getScrollX();

        if (deltaX < 0) {
          if (scrollX > 0) {
            scrollBy(Math.max(-scrollX, deltaX), 0);
          }
        } else if (deltaX > 0) {
          final int availableToScroll = getChildAt(getChildCount() - 1).getRight() - scrollX - getWidth();
          if (availableToScroll > 0) {
            scrollBy(Math.min(availableToScroll, deltaX), 0);
          }
        }

        mLastMotionX = x;
        mLastMotionY = y;
      }
      break;
    case MotionEvent.ACTION_UP:
      if (isDragging) {
        final VelocityTracker velocityTracker = mVelocityTracker;
        velocityTracker.computeCurrentVelocity(VELOCITY_UNIT_PIXELS_PER_SECOND, mMaximumVelocity);
        final int velocityX = (int) velocityTracker.getXVelocity();

        if (velocityX > mDensityAdjustedSnapVelocity && mCurrentScreen > 0) {
          snapToScreen(mCurrentScreen - 1);
        } else if (velocityX < -mDensityAdjustedSnapVelocity && mCurrentScreen < getChildCount() - 1) {
          snapToScreen(mCurrentScreen + 1);
        } else {
          snapToDestination();
        }

        if (mVelocityTracker != null) {
          mVelocityTracker.recycle();
          mVelocityTracker = null;
        }
      }
      isDragging = false;
      break;
    case MotionEvent.ACTION_CANCEL:
      if (isDragging) {
        isDragging = false;
        snapToDestination();
      }
      break;
    default:
      break;
    }

    return true;
  }

  public void setCurrentScreen(final int currentScreen, final boolean animate) {
    mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
    if (animate) {
      snapToScreen(currentScreen, ANIMATION_SCREEN_SET_DURATION_MILLIS);
    } else {
      scrollTo(mCurrentScreen * getWidth(), 0);
    }
    invalidate();
  }

  public void setListener(final HorizontalPagerListener listener) {
    this.listener = listener;
  }

  private void snapToDestination() {
    final int screenWidth = getWidth();
    final int scrollX = getScrollX();
    final int deltaX = scrollX - (screenWidth * mCurrentScreen);
    int whichScreen = mCurrentScreen;

    if ((deltaX < 0) && mCurrentScreen != 0 && ((screenWidth / FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE) < -deltaX)) {
      whichScreen--;
    } else if ((deltaX > 0) && (mCurrentScreen + 1 != getChildCount())
        && ((screenWidth / FRACTION_OF_SCREEN_WIDTH_FOR_SWIPE) < deltaX)) {
      whichScreen++;
    }

    snapToScreen(whichScreen);
  }

  private void snapToScreen(final int whichScreen) {
    snapToScreen(whichScreen, -1);
  }

  private void snapToScreen(final int whichScreen, final int duration) {
    mNextScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
    final int newX = mNextScreen * getWidth();
    final int delta = newX - getScrollX();

    if (duration < 0) {
      scroller.startScroll(getScrollX(), 0, delta, 0,
          (int) (Math.abs(delta) / (float) getWidth() * ANIMATION_SCREEN_SET_DURATION_MILLIS));
    } else {
      scroller.startScroll(getScrollX(), 0, delta, 0, duration);
    }

    invalidate();
  }
}




Java Source Code List

tv.huohua.peterson.api.AbsApi.java
tv.huohua.peterson.api.AbsListApi.java
tv.huohua.peterson.api.ApiCallResponse.java
tv.huohua.peterson.misc.ApplicationUtils.java
tv.huohua.peterson.misc.DeviceUtils.java
tv.huohua.peterson.misc.IOUtils.java
tv.huohua.peterson.misc.JavaLangUtils.java
tv.huohua.peterson.misc.Pair.java
tv.huohua.peterson.network.HttpRequest.java
tv.huohua.peterson.network.NetworkMgr.java
tv.huohua.peterson.network.NetworkUtils.java
tv.huohua.peterson.social.ISocialAuthorizer.java
tv.huohua.peterson.social.TencentWeiboAccessTokenKeeper.java
tv.huohua.peterson.social.TencentWeiboAuthorizer.java
tv.huohua.peterson.social.WeiboAccessTokenKeeper.java
tv.huohua.peterson.social.WeiboApiCaller.java
tv.huohua.peterson.social.WeiboAuthorizer.java
tv.huohua.peterson.view.FixedAspectRatioImageView.java
tv.huohua.peterson.view.FixedAspectRatioRelativeLayout.java
tv.huohua.peterson.view.HHListView.java
tv.huohua.peterson.view.HorizontalPagerListener.java
tv.huohua.peterson.view.HorizontalPager.java