// 记录缩放前的一些信息 private void saveScaleContext(float x1, float y1, float x2, float y2) { mScaleBase = MathUtils.getMatrixScale(mOuterMatrix)[0] / MathUtils.getDistance(x1, y1, x2, y2); // 获取缩放缩放点中点在第一层变换后的图片上的坐标 float[] center = MathUtils.inverseMatrixPoint(MathUtils.getCenterPoint(x1, y1, x2, y2), mOuterMatrix); mScaleCenter.set(center[0], center[1]); }
// 当缩放操作结束如果不在正确位置用动画恢复 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(); } }
// 双击后放大或者缩小 // 当当前缩放比例大于等于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(); }