下面列出了android.graphics.Matrix#postConcat ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix) {
float viewWidth = getWidth();
float viewHeight = getHeight();
float w = bitmap.getWidth();
float h = bitmap.getHeight();
int rotation = bitmap.getRotation();
matrix.reset();
// We limit up-scaling to 2x otherwise the result may look bad if it's
// a small icon.
float widthScale = Math.min(viewWidth / w, 2.0f);
float heightScale = Math.min(viewHeight / h, 2.0f);
float scale = Math.min(widthScale, heightScale);
matrix.postConcat(bitmap.getRotateMatrix());
matrix.postScale(scale, scale);
matrix.postTranslate(
(viewWidth - w * scale) / 2F,
(viewHeight - h * scale) / 2F);
}
private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix, boolean includeRotation) {
float viewWidth = getWidth();
float viewHeight = getHeight();
float w = bitmap.getWidth();
float h = bitmap.getHeight();
matrix.reset();
// We limit up-scaling to 3x otherwise the result may look bad if it's a small icon
float widthScale = Math.min(viewWidth / w, 3.0f);
float heightScale = Math.min(viewHeight / h, 3.0f);
float scale = Math.min(widthScale, heightScale);
if (includeRotation) {
matrix.postConcat(bitmap.getRotateMatrix());
}
matrix.postScale(scale, scale);
matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h * scale) / 2F);
}
private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix, boolean includeRotation) {
float viewWidth = getWidth();
float viewHeight = getHeight();
float w = bitmap.getWidth();
float h = bitmap.getHeight();
matrix.reset();
// We limit up-scaling to 3x otherwise the result may look bad if it's a small icon
float widthScale = Math.min(viewWidth / w, 3.0f);
float heightScale = Math.min(viewHeight / h, 3.0f);
float scale = Math.min(widthScale, heightScale);
if (includeRotation) {
matrix.postConcat(bitmap.getRotateMatrix());
}
matrix.postScale(scale, scale);
matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h * scale) / 2F);
}
@Override
public void applyMatrixForData(Matrix matrix) {
super.applyMatrixForData(matrix);
for (DrawElement element : elements) {
// Before applying data matrix, it should transfer the display matrices to data.
// After that, it should revert back to original display matrix.
Matrix parentInvertDisplay = new Matrix(getInvertedDisplayMatrix());
Matrix originalDisplay = new Matrix(element.getDisplayMatrix());
originalDisplay.postConcat(parentInvertDisplay);
Matrix originalInvertDisplay = new Matrix();
originalDisplay.invert(originalInvertDisplay);
element.applyDisplayMatrixToData();
element.applyMatrixForData(matrix);
element.applyMatrixForData(originalInvertDisplay);
element.getDisplayMatrix().postConcat(originalDisplay);
element.updateBoundingBox();
}
recalculateBoundingBox();
}
/**
* Sets a matrix such that given a two rotations, that it transforms coordinates given in the
* old rotation to coordinates that refer to the same physical location in the new rotation.
*
* @param oldRotation the rotation to transform from
* @param newRotation the rotation to transform to
* @param info the display info
* @param out a matrix that will be set to the transform
*/
public static void transformToRotation(@Rotation int oldRotation,
@Rotation int newRotation, DisplayInfo info, Matrix out) {
final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
final int h = flipped ? info.logicalWidth : info.logicalHeight;
final int w = flipped ? info.logicalHeight : info.logicalWidth;
final Matrix tmp = new Matrix();
transformLogicalToPhysicalCoordinates(oldRotation, w, h, out);
transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
out.postConcat(tmp);
}
/**
* Sets a matrix such that given a two rotations, that it transforms coordinates given in the
* old rotation to coordinates that refer to the same physical location in the new rotation.
*
* @param oldRotation the rotation to transform from
* @param newRotation the rotation to transform to
* @param newWidth the width of the area to transform, in the new rotation
* @param newHeight the height of the area to transform, in the new rotation
* @param out a matrix that will be set to the transform
*/
public static void transformToRotation(@Rotation int oldRotation,
@Rotation int newRotation, int newWidth, int newHeight, Matrix out) {
final boolean flipped = newRotation == ROTATION_90 || newRotation == ROTATION_270;
final int h = flipped ? newWidth : newHeight;
final int w = flipped ? newHeight : newWidth;
final Matrix tmp = new Matrix();
transformLogicalToPhysicalCoordinates(oldRotation, w, h, out);
transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
out.postConcat(tmp);
}
/**
* Returns a matrix that maps bounds to the crop area.
*/
public Matrix getInverseCropPosition() {
Matrix matrix = new Matrix();
matrix.set(findRelativeMatrix(editorElementHierarchy.getMainImage(), editorElementHierarchy.getCropEditorElement()));
matrix.postConcat(editorElementHierarchy.getFlipRotate().getLocalMatrix());
Matrix positionRelativeToCrop = new Matrix();
matrix.invert(positionRelativeToCrop);
return positionRelativeToCrop;
}
public ImageViewAnimationBuilder imageMatrixBy(Matrix deltaValue) {
Matrix matrix = new Matrix(mView.getImageMatrix());
matrix.postConcat(deltaValue);
return imageMatrix(matrix);
}
/**
* 双击后放大或者缩小
*
* 将图片缩放比例缩放到nextScale指定的值.
* 但nextScale值不能大于最大缩放值不能小于fit center情况下的缩放值.
* 将双击的点尽量移动到控件中心.
*
* @param x 双击的点
* @param y 双击的点
*
* @see #calculateNextScale(float, float)
* @see #getMaxScale()
*/
private void doubleTap(float x, float y) {
if (!isReady()) {
return;
}
//获取第一层变换矩阵
Matrix innerMatrix = MathUtils.matrixTake();
getInnerMatrix(innerMatrix);
//当前总的缩放比例
float innerScale = MathUtils.getMatrixScale(innerMatrix)[0];
float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
float currentScale = innerScale * outerScale;
//控件大小
float displayWidth = getWidth();
float displayHeight = getHeight();
//最大放大大小
float maxScale = getMaxScale();
//接下来要放大的大小
float nextScale = calculateNextScale(innerScale, outerScale);
//如果接下来放大大于最大值或者小于fit center值,则取边界
if (nextScale > maxScale) {
nextScale = maxScale;
}
if (nextScale < innerScale) {
nextScale = innerScale;
}
//开始计算缩放动画的结果矩阵
Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);
//计算还需缩放的倍数
animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);
//将放大点移动到控件中心
animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y);
//得到放大之后的图片方框
Matrix testMatrix = MathUtils.matrixTake(innerMatrix);
testMatrix.postConcat(animEnd);
RectF testBound = MathUtils.rectFTake(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
testMatrix.mapRect(testBound);
//修正位置
float postX = 0;
float postY = 0;
if (testBound.right - testBound.left < displayWidth) {
postX = displayWidth / 2f - (testBound.right + testBound.left) / 2f;
} 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 / 2f - (testBound.bottom + testBound.top) / 2f;
} else if (testBound.top > 0) {
postY = -testBound.top;
} else if (testBound.bottom < displayHeight) {
postY = displayHeight - testBound.bottom;
}
//应用修正位置
animEnd.postTranslate(postX, postY);
//清理当前可能正在执行的动画
cancelAllAnimator();
//启动矩阵动画
mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);
mScaleAnimator.start();
//清理临时变量
MathUtils.rectFGiven(testBound);
MathUtils.matrixGiven(testMatrix);
MathUtils.matrixGiven(animEnd);
MathUtils.matrixGiven(innerMatrix);
}
public Matrix getUnrotatedMatrix(){
Matrix unrotated = new Matrix();
getProperBaseMatrix(bitmapDisplayed, unrotated, false);
unrotated.postConcat(suppMatrix);
return unrotated;
}
public void getConcatMatrix(Matrix toMatrix) {
toMatrix.postConcat(matrix);
}
public Matrix getUnrotatedMatrix(){
Matrix unrotated = new Matrix();
getProperBaseMatrix(bitmapDisplayed, unrotated, false);
unrotated.postConcat(suppMatrix);
return unrotated;
}
/**
* 双击后放大或者缩小
* <p>
* 将图片缩放比例缩放到nextScale指定的值.
* 但nextScale值不能大于最大缩放值不能小于fit center情况下的缩放值.
* 将双击的点尽量移动到控件中心.
*
* @param x 双击的点
* @param y 双击的点
* @see #calculateNextScale(float, float)
* @see #getMaxScale()
*/
private void doubleTap(float x, float y) {
if (!isReady()) {
return;
}
//获取第一层变换矩阵
Matrix innerMatrix = MathUtils.matrixTake();
getInnerMatrix(innerMatrix);
//当前总的缩放比例
float innerScale = MathUtils.getMatrixScale(innerMatrix)[0];
float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
float currentScale = innerScale * outerScale;
//控件大小
float displayWidth = getWidth();
float displayHeight = getHeight();
//最大放大大小
float maxScale = getMaxScale();
//接下来要放大的大小
float nextScale = calculateNextScale(innerScale, outerScale);
//如果接下来放大大于最大值或者小于fit center值,则取边界
if (nextScale > maxScale) {
nextScale = maxScale;
}
if (nextScale < innerScale) {
nextScale = innerScale;
}
//开始计算缩放动画的结果矩阵
Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);
//计算还需缩放的倍数
animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);
//将放大点移动到控件中心
animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y);
//得到放大之后的图片方框
Matrix testMatrix = MathUtils.matrixTake(innerMatrix);
testMatrix.postConcat(animEnd);
RectF testBound = MathUtils.rectFTake(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
testMatrix.mapRect(testBound);
//修正位置
float postX = 0;
float postY = 0;
if (testBound.right - testBound.left < displayWidth) {
postX = displayWidth / 2f - (testBound.right + testBound.left) / 2f;
} 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 / 2f - (testBound.bottom + testBound.top) / 2f;
} else if (testBound.top > 0) {
postY = -testBound.top;
} else if (testBound.bottom < displayHeight) {
postY = displayHeight - testBound.bottom;
}
//应用修正位置
animEnd.postTranslate(postX, postY);
//清理当前可能正在执行的动画
cancelAllAnimator();
//启动矩阵动画
mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);
mScaleAnimator.start();
//清理临时变量
MathUtils.rectFGiven(testBound);
MathUtils.matrixGiven(testMatrix);
MathUtils.matrixGiven(animEnd);
MathUtils.matrixGiven(innerMatrix);
}
/**
* 双击后放大或者缩小
*
* 将图片缩放比例缩放到nextScale指定的值.
* 但nextScale值不能大于最大缩放值不能小于fit center情况下的缩放值.
* 将双击的点尽量移动到控件中心.
*
* @param x 双击的点
* @param y 双击的点
*
* @see #calculateNextScale(float, float)
* @see #getMaxScale()
*/
private void doubleTap(float x, float y) {
if (!isReady()) {
return;
}
//获取第一层变换矩阵
Matrix innerMatrix = MathUtils.matrixTake();
getInnerMatrix(innerMatrix);
//当前总的缩放比例
float innerScale = MathUtils.getMatrixScale(innerMatrix)[0];
float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
float currentScale = innerScale * outerScale;
//控件大小
float displayWidth = getWidth();
float displayHeight = getHeight();
//最大放大大小
float maxScale = getMaxScale();
//接下来要放大的大小
float nextScale = calculateNextScale(innerScale, outerScale);
//如果接下来放大大于最大值或者小于fit center值,则取边界
if (nextScale > maxScale) {
nextScale = maxScale;
}
if (nextScale < innerScale) {
nextScale = innerScale;
}
//开始计算缩放动画的结果矩阵
Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);
//计算还需缩放的倍数
animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);
//将放大点移动到控件中心
animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y);
//得到放大之后的图片方框
Matrix testMatrix = MathUtils.matrixTake(innerMatrix);
testMatrix.postConcat(animEnd);
RectF testBound = MathUtils.rectFTake(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
testMatrix.mapRect(testBound);
//修正位置
float postX = 0;
float postY = 0;
if (testBound.right - testBound.left < displayWidth) {
postX = displayWidth / 2f - (testBound.right + testBound.left) / 2f;
} 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 / 2f - (testBound.bottom + testBound.top) / 2f;
} else if (testBound.top > 0) {
postY = -testBound.top;
} else if (testBound.bottom < displayHeight) {
postY = displayHeight - testBound.bottom;
}
//应用修正位置
animEnd.postTranslate(postX, postY);
//清理当前可能正在执行的动画
cancelAllAnimator();
//启动矩阵动画
mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);
mScaleAnimator.start();
//清理临时变量
MathUtils.rectFGiven(testBound);
MathUtils.matrixGiven(testMatrix);
MathUtils.matrixGiven(animEnd);
MathUtils.matrixGiven(innerMatrix);
}
/**
* 双击后放大或者缩小
*
* 将图片缩放比例缩放到nextScale指定的值.
* 但nextScale值不能大于最大缩放值不能小于fit center情况下的缩放值.
* 将双击的点尽量移动到控件中心.
*
* @param x 双击的点
* @param y 双击的点
*
* @see #calculateNextScale(float, float)
* @see #getMaxScale()
*/
private void doubleTap(float x, float y) {
if (!isReady()) {
return;
}
//获取第一层变换矩阵
Matrix innerMatrix = MathUtils.matrixTake();
getInnerMatrix(innerMatrix);
//当前总的缩放比例
float innerScale = MathUtils.getMatrixScale(innerMatrix)[0];
float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
float currentScale = innerScale * outerScale;
//控件大小
float displayWidth = getWidth();
float displayHeight = getHeight();
//最大放大大小
float maxScale = getMaxScale();
//接下来要放大的大小
float nextScale = calculateNextScale(innerScale, outerScale);
//如果接下来放大大于最大值或者小于fit center值,则取边界
if (nextScale > maxScale) {
nextScale = maxScale;
}
if (nextScale < innerScale) {
nextScale = innerScale;
}
//开始计算缩放动画的结果矩阵
Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);
//计算还需缩放的倍数
animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);
//将放大点移动到控件中心
animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y);
//得到放大之后的图片方框
Matrix testMatrix = MathUtils.matrixTake(innerMatrix);
testMatrix.postConcat(animEnd);
RectF testBound = MathUtils.rectFTake(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
testMatrix.mapRect(testBound);
//修正位置
float postX = 0;
float postY = 0;
if (testBound.right - testBound.left < displayWidth) {
postX = displayWidth / 2f - (testBound.right + testBound.left) / 2f;
} 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 / 2f - (testBound.bottom + testBound.top) / 2f;
} else if (testBound.top > 0) {
postY = -testBound.top;
} else if (testBound.bottom < displayHeight) {
postY = displayHeight - testBound.bottom;
}
//应用修正位置
animEnd.postTranslate(postX, postY);
//清理当前可能正在执行的动画
cancelAllAnimator();
//启动矩阵动画
mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);
mScaleAnimator.start();
//清理临时变量
MathUtils.rectFGiven(testBound);
MathUtils.matrixGiven(testMatrix);
MathUtils.matrixGiven(animEnd);
MathUtils.matrixGiven(innerMatrix);
}
@SuppressWarnings("deprecation")
private void doStroke(Path path)
{
// TODO handle degenerate subpaths properly
if (state.style.vectorEffect == VectorEffect.NonScalingStroke)
{
// For non-scaling-stroke, the stroke width is not transformed along with the path.
// It will be rendered at the same width no matter how the document contents are transformed.
// First step: get the current canvas matrix
Matrix currentMatrix = canvas.getMatrix();
// Transform the path using this transform
Path transformedPath = new Path();
path.transform(currentMatrix, transformedPath);
// Reset the current canvas transform completely
canvas.setMatrix(new Matrix());
// If there is a shader (such as a gradient), we need to update its transform also
Shader shader = state.strokePaint.getShader();
Matrix currentShaderMatrix = new Matrix();
if (shader != null) {
shader.getLocalMatrix(currentShaderMatrix);
Matrix newShaderMatrix = new Matrix(currentShaderMatrix);
newShaderMatrix.postConcat(currentMatrix);
shader.setLocalMatrix(newShaderMatrix);
}
// Render the transformed path. The stroke width used will be in unscaled device units.
canvas.drawPath(transformedPath, state.strokePaint);
// Return the current canvas transform to what it was before all this happened
canvas.setMatrix(currentMatrix);
// And reset the shader matrix also
if (shader != null)
shader.setLocalMatrix(currentShaderMatrix);
}
else
{
canvas.drawPath(path, state.strokePaint);
}
}
public void getConcatMatrix(Matrix toMatrix) {
toMatrix.postConcat(matrix);
}
/**
* 获取图片总变换矩阵.
*
* 总变换矩阵为内部变换矩阵x外部变换矩阵,决定了原图到所见最终状态的变换
* 当尚未布局或者原图不存在时,其值无意义.所以在调用前需要确保前置条件有效,否则将影响计算结果.
*
* @param matrix 用于填充结果的对象
* @return 如果传了matrix参数则将matrix填充后返回,否则new一个填充返回
*
* @see #getOuterMatrix(Matrix)
* @see #getInnerMatrix(Matrix)
*/
public Matrix getCurrentImageMatrix(Matrix matrix) {
//获取内部变换矩阵
matrix = getInnerMatrix(matrix);
//乘上外部变换矩阵
matrix.postConcat(mOuterMatrix);
return matrix;
}
/**
* 获取图片总变换矩阵.
* <p>
* 总变换矩阵为内部变换矩阵x外部变换矩阵,决定了原图到所见最终状态的变换
* 当尚未布局或者原图不存在时,其值无意义.所以在调用前需要确保前置条件有效,否则将影响计算结果.
*
* @param matrix 用于填充结果的对象
* @return 如果传了matrix参数则将matrix填充后返回, 否则new一个填充返回
* @see #getOuterMatrix(Matrix)
* @see #getInnerMatrix(Matrix)
*/
public Matrix getCurrentImageMatrix(Matrix matrix) {
//获取内部变换矩阵
matrix = getInnerMatrix(matrix);
//乘上外部变换矩阵
matrix.postConcat(mOuterMatrix);
return matrix;
}
/**
* Calculates the transformation matrix according to M(transformation) * M(source) = M(target).
*
* @param source source matrix
* @param target target matrix
* @return delta matrix
*/
public static Matrix getTransformationMatrix(Matrix source, Matrix target) {
Matrix delta = new Matrix();
source.invert(delta);
delta.postConcat(target);
return delta;
}