Example #1
0
 private void fling(float vx, float vy) {
   // 以修正动画为大,遇到修正动画正在执行,就不执行惯性动画
   if (!(mScaleAnimator != null && mScaleAnimator.isRunning()) && getDrawable() != null) {
     if (mFlingAnimator != null) {
       mFlingAnimator.cancel();
       mFlingAnimator = null;
     }
     mFlingAnimator = new FlingAnimator(new float[] {vx / 1000 * 16, vy / 1000 * 16});
     mFlingAnimator.start();
   }
 }
Example #2
0
 public boolean animFromTo(Matrix matrixFrom, Matrix matrixTo) {
   if (getDrawable() == null) {
     return false;
   }
   if (mScaleAnimator != null) {
     mScaleAnimator.cancel();
     mScaleAnimator = null;
   }
   if (mFlingAnimator != null) {
     mFlingAnimator.cancel();
     mFlingAnimator = null;
   }
   mScaleAnimator = new ScaleAnimator(matrixFrom, matrixTo);
   mScaleAnimator.start();
   return true;
 }
Example #3
0
 // 停止所有动画,重置位置到fit center状态
 public void reset() {
   mOuterMatrix = new Matrix();
   onOuterMatrixChanged();
   mPinchMode = PINCH_MODE_FREE;
   mLastMovePoint = new PointF();
   mScaleCenter = new PointF();
   mScaleBase = 0;
   if (mScaleAnimator != null) {
     mScaleAnimator.cancel();
     mScaleAnimator = null;
   }
   if (mFlingAnimator != null) {
     mFlingAnimator.cancel();
     mFlingAnimator = null;
   }
   invalidate();
 }
Example #4
0
 // 当缩放操作结束如果不在正确位置用动画恢复
 private void scaleEnd() {
   // 不允许动画过程中再触发
   if ((mScaleAnimator != null && mScaleAnimator.isRunning()) || getDrawable() == null) {
     return;
   }
   // 是否修正了位置
   boolean change = false;
   // 获取图片整体的变换矩阵
   Matrix currentMatrix = getCurrentImageMatrix();
   // 整体缩放比例
   float currentScale = MathUtils.getMatrixScale(currentMatrix)[0];
   // 第二层缩放比例
   float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
   // 控件大小
   float displayWidth = getMeasuredWidth();
   float displayHeight = getMeasuredHeight();
   float maxScale = getMaxScale();
   // 比例修正
   float scalePost = 1;
   // 位置修正
   float postX = 0;
   float postY = 0;
   // 如果整体缩放比例大于最大比例,进行缩放修正
   if (currentScale > maxScale) {
     scalePost = maxScale / currentScale;
   }
   // 如果缩放修正后整体导致第二层缩放小于1(就是图片比fit center状态还小),重新修正缩放
   if (outerScale * scalePost < 1) {
     scalePost = 1 / outerScale;
   }
   // 如果修正不为1,说明进行了修正
   if (scalePost != 1) {
     change = true;
   }
   // 尝试根据缩放点进行缩放修正
   Matrix testMatrix = new Matrix(currentMatrix);
   testMatrix.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y);
   RectF testBound =
       new RectF(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
   // 获取缩放修正后的图片方框
   testMatrix.mapRect(testBound);
   // 检测缩放修正后位置有无超出,如果超出进行位置修正
   if (testBound.right - testBound.left < displayWidth) {
     postX = displayWidth / 2 - (testBound.right + testBound.left) / 2;
   } else if (testBound.left > 0) {
     postX = -testBound.left;
   } else if (testBound.right < displayWidth) {
     postX = displayWidth - testBound.right;
   }
   if (testBound.bottom - testBound.top < displayHeight) {
     postY = displayHeight / 2 - (testBound.bottom + testBound.top) / 2;
   } else if (testBound.top > 0) {
     postY = -testBound.top;
   } else if (testBound.bottom < displayHeight) {
     postY = displayHeight - testBound.bottom;
   }
   // 如果位置修正不为0,说明进行了修正
   if (postX != 0 || postY != 0) {
     change = true;
   }
   // 只有有执行修正才执行动画
   if (change) {
     // 如果up的时候触发惯性,这里需要取消掉,以修正动画为主
     if (mFlingAnimator != null) {
       mFlingAnimator.cancel();
       mFlingAnimator = null;
     }
     // 动画开始举证
     Matrix animStart = new Matrix(mOuterMatrix);
     // 计算结束举证
     Matrix animEnd = new Matrix(mOuterMatrix);
     animEnd.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y);
     animEnd.postTranslate(postX, postY);
     // 启动矩阵动画
     mScaleAnimator = new ScaleAnimator(animStart, animEnd);
     mScaleAnimator.start();
   }
 }
Example #5
0
 // 双击后放大或者缩小
 // 当当前缩放比例大于等于1,那么双击放大到MaxScale
 // 当当前缩放比例小于1,双击放大到1
 // 当当前缩放比例等于MaxScale,双击缩小到屏幕大小
 private void doubleTap(float x, float y) {
   // 不允许动画过程中再触发
   if ((mScaleAnimator != null && mScaleAnimator.isRunning()) || getDrawable() == null) {
     return;
   }
   // 获取第一层变换矩阵
   Matrix innerMatrix = getInnerMatrix();
   // 当前总的缩放比例
   float innerScale = MathUtils.getMatrixScale(innerMatrix)[0];
   float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
   float currentScale = innerScale * outerScale;
   // 控件大小
   float displayWidth = getMeasuredWidth();
   float displayHeight = getMeasuredHeight();
   // 最大放大大小
   float maxScale = getMaxScale();
   // 接下来要放大的大小
   float nextScale = calculateNextScale(innerScale, outerScale);
   // 如果接下来放大大于最大值或者小于fit center值,则取边界
   if (nextScale < innerScale) {
     nextScale = innerScale;
   } else if (nextScale > maxScale) {
     nextScale = maxScale;
   }
   // 缩放动画初始矩阵为当前矩阵值
   Matrix animStart = new Matrix(mOuterMatrix);
   // 开始计算缩放动画的结果矩阵
   Matrix animEnd = new Matrix(mOuterMatrix);
   // 计算还需缩放的倍数
   animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);
   // 将放大点移动到控件中心
   animEnd.postTranslate(displayWidth / 2 - x, displayHeight / 2 - y);
   // 得到放大之后的图片方框
   Matrix testMatrix = new Matrix(innerMatrix);
   testMatrix.postConcat(animEnd);
   RectF testBound =
       new RectF(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
   testMatrix.mapRect(testBound);
   // 修正位置
   float postX = 0;
   float postY = 0;
   if (testBound.right - testBound.left < displayWidth) {
     postX = displayWidth / 2 - (testBound.right + testBound.left) / 2;
   } else if (testBound.left > 0) {
     postX = -testBound.left;
   } else if (testBound.right < displayWidth) {
     postX = displayWidth - testBound.right;
   }
   if (testBound.bottom - testBound.top < displayHeight) {
     postY = displayHeight / 2 - (testBound.bottom + testBound.top) / 2;
   } else if (testBound.top > 0) {
     postY = -testBound.top;
   } else if (testBound.bottom < displayHeight) {
     postY = displayHeight - testBound.bottom;
   }
   // 应用修正位置
   animEnd.postTranslate(postX, postY);
   // 如果正在执行惯性动画,则取消掉
   if (mFlingAnimator != null) {
     mFlingAnimator.cancel();
     mFlingAnimator = null;
   }
   // 启动矩阵动画
   mScaleAnimator = new ScaleAnimator(animStart, animEnd);
   mScaleAnimator.start();
 }
Example #6
0
 @Override
 public boolean onTouchEvent(MotionEvent event) {
   super.onTouchEvent(event);
   if (mPinchMode == PINCH_MODE_NO_PINCH) {
     return true;
   }
   // 无论如何都处理各种外部手势
   mGestureDetector.onTouchEvent(event);
   int action = event.getAction() & MotionEvent.ACTION_MASK;
   // 最后一个点抬起或者取消,结束所有模式
   if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
     if (mPinchMode == PINCH_MODE_SCALE) {
       scaleEnd();
     }
     mPinchMode = PINCH_MODE_FREE;
   } else if (action == MotionEvent.ACTION_POINTER_UP) {
     if (mPinchMode == PINCH_MODE_SCALE) {
       // 抬起的点如果大于2,那么缩放模式还有效,但是有可能初始点变了,重新测量初始点
       if (event.getPointerCount() > 2) {
         // 如果还没结束缩放模式,但是第一个点抬起了,那么让第二个点和第三个点作为缩放控制点
         if (event.getAction() >> 8 == 0) {
           saveScaleContext(event.getX(1), event.getY(1), event.getX(2), event.getY(2));
           // 如果还没结束缩放模式,但是第二个点抬起了,那么让第一个点和第三个点作为缩放控制点
         } else if (event.getAction() >> 8 == 1) {
           saveScaleContext(event.getX(0), event.getY(0), event.getX(2), event.getY(2));
         }
       }
     }
     // 第一个点按下,开启滚动模式,记录开始滚动的点
   } else if (action == MotionEvent.ACTION_DOWN) {
     // 在矩阵动画过程中不允许启动滚动模式
     if (!(mScaleAnimator != null && mScaleAnimator.isRunning())) {
       // 停止惯性滚动
       if (mFlingAnimator != null) {
         mFlingAnimator.cancel();
         mFlingAnimator = null;
       }
       mPinchMode = PINCH_MODE_SCROLL;
       mLastMovePoint.set(event.getX(), event.getY());
     }
     // 非第一个点按下,关闭滚动模式,开启缩放模式,记录缩放模式的一些初始数据
   } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
     // 停止惯性滚动
     if (mFlingAnimator != null) {
       mFlingAnimator.cancel();
       mFlingAnimator = null;
     }
     // 停止矩阵动画
     if (mScaleAnimator != null) {
       mScaleAnimator.cancel();
       mScaleAnimator = null;
     }
     mPinchMode = PINCH_MODE_SCALE;
     saveScaleContext(event.getX(0), event.getY(0), event.getX(1), event.getY(1));
   } else if (action == MotionEvent.ACTION_MOVE) {
     if (!(mScaleAnimator != null && mScaleAnimator.isRunning())) {
       // 在滚动模式下移动
       if (mPinchMode == PINCH_MODE_SCROLL) {
         // 每次移动产生一个差值累积到图片位置上
         scrollBy(event.getX() - mLastMovePoint.x, event.getY() - mLastMovePoint.y);
         // 记录新的移动点
         mLastMovePoint.set(event.getX(), event.getY());
         // 在缩放模式下移动
       } else if (mPinchMode == PINCH_MODE_SCALE && event.getPointerCount() > 1) {
         // 两个缩放点间的距离
         float distance =
             MathUtils.getDistance(event.getX(0), event.getY(0), event.getX(1), event.getY(1));
         // 保存缩放点中点
         float[] lineCenter =
             MathUtils.getCenterPoint(event.getX(0), event.getY(0), event.getX(1), event.getY(1));
         mLastMovePoint.set(lineCenter[0], lineCenter[1]);
         // 处理缩放
         scale(mScaleCenter, mScaleBase, distance, mLastMovePoint);
       }
     }
   }
   return true;
 }