+ mImageWidth - IMAGE_PADDING, mHeight); childView.initImageViewBitmap(); left = left + mImageWidth; } refreshImageShowing(); } forceToRelayout = false; } } @Override public boolean onTouchEvent(MotionEvent event) { if (mScroller.isFinished()) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); int action = event.getAction(); float x = event.getX(); switch (action) { case MotionEvent.ACTION_DOWN: // 记录按下时的横坐标 mLastMotionX = x; break; case MotionEvent.ACTION_MOVE: int disX = (int) (mLastMotionX - x); mLastMotionX = x; scrollBy(disX, 0); // 当发生移动时刷新图片的显示状态 refreshImageShowing(); break; case MotionEvent.ACTION_UP: mVelocityTracker.computeCurrentVelocity(1000); int velocityX = (int) mVelocityTracker.getXVelocity(); if (shouldScrollToNext(velocityX)) { // 滚动到下一张图 scrollToNext(); } else if (shouldScrollToPrevious(velocityX)) {
}
} }
return true;
// 滚动到上一张图 scrollToPrevious(); } else { // 滚动回当前图片 scrollBack(); }
if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; }
break;
/**
* 根据当前的触摸状态来决定是否屏蔽子控件的交互能力。 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { return true; } float x = ev.getX(); switch (action) { case MotionEvent.ACTION_DOWN: mLastMotionX = x; mTouchState = TOUCH_STATE_REST; break; case MotionEvent.ACTION_MOVE: int xDiff = (int) Math.abs(mLastMotionX - x); if (xDiff > mTouchSlop) { mTouchState = TOUCH_STATE_SCROLLING; } break; case MotionEvent.ACTION_UP: default: mTouchState = TOUCH_STATE_REST; break; } return mTouchState != TOUCH_STATE_REST;
} @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); refreshImageShowing(); postInvalidate(); } } /** * 设置图片滚动的监听器,每当有图片滚动时会回调此接口。 * * @param listener * 图片滚动监听器 */ public void setOnImageSwitchListener(OnImageSwitchListener listener) { mListener = listener; } /** * 设置当前显示图片的下标,注意如果该值小于零或大于等于图片的总数量,图片则无法正常显示。 * * @param currentImage * 图片的下标 */ public void setCurrentImage(int currentImage) { mCurrentImage = currentImage; requestLayout(); } /** * 滚动到下一张图片。 */ public void scrollToNext() { if (mScroller.isFinished()) { int disX = mImageWidth - getScrollX(); checkImageSwitchBorder(SCROLL_NEXT); if (mListener != null) {
mListener.onImageSwitch(mCurrentImage); } beginScroll(getScrollX(), 0, disX, 0, SCROLL_NEXT); } } /** * 滚动到上一张图片。 */ public void scrollToPrevious() { if (mScroller.isFinished()) { int disX = -mImageWidth - getScrollX(); checkImageSwitchBorder(SCROLL_PREVIOUS); if (mListener != null) { mListener.onImageSwitch(mCurrentImage); } beginScroll(getScrollX(), 0, disX, 0, SCROLL_PREVIOUS); } } /** * 滚动回原图片。 */ public void scrollBack() { if (mScroller.isFinished()) { beginScroll(getScrollX(), 0, -getScrollX(), 0, SCROLL_BACK); } } /** * 回收所有图片对象,释放内存。 */ public void clear() { for (int i = 0; i < mCount; i++) { Image3DView childView = (Image3DView) getChildAt(i); childView.recycleBitmap(); } }
/** * 让控件中的所有图片开始滚动。 */ private void beginScroll(int startX, int startY, int dx, int dy, final int action) { int duration = (int) (700f / mImageWidth * Math.abs(dx)); mScroller.startScroll(startX, startY, dx, dy, duration); invalidate(); handler.postDelayed(new Runnable() { @Override public void run() { if (action == SCROLL_NEXT || action == SCROLL_PREVIOUS) { forceToRelayout = true; requestLayout(); } } }, duration); } /** * 根据当前图片的下标和传入的item参数,来判断item位置上应该显示哪张图片。 * * @param item * 取值范围是1-5 * @return 对应item位置上应该显示哪张图片。 */ private int getIndexForItem(int item) { int index = -1; index = mCurrentImage + item - 3; while (index < 0) { index = index + mCount; } while (index > mCount - 1) { index = index - mCount; } return index; } /** * 刷新所有图片的显示状态,包括当前的旋转角度。