下面列出了android.graphics.Matrix#MSCALE_X 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* After rotating, the matrix needs to be translated. This function finds the area of image
* which was previously centered and adjusts translations so that is again the center, post-rotation.
*
* @param axis Matrix.MTRANS_X or Matrix.MTRANS_Y
* @param trans the value of trans in that axis before the rotation
* @param prevImageSize the width/height of the image before the rotation
* @param imageSize width/height of the image after rotation
* @param prevViewSize width/height of view before rotation
* @param viewSize width/height of view after rotation
* @param drawableSize width/height of drawable
*/
private void translateMatrixAfterRotate(int axis, float trans, float prevImageSize, float imageSize, int prevViewSize, int viewSize, int drawableSize) {
if (imageSize < viewSize) {
//
// The width/height of image is less than the view's width/height. Center it.
//
m[axis] = (viewSize - (drawableSize * m[Matrix.MSCALE_X])) * 0.5f;
} else if (trans > 0) {
//
// The image is larger than the view, but was not before rotation. Center it.
//
m[axis] = -((imageSize - viewSize) * 0.5f);
} else {
//
// Find the area of the image which was previously centered in the view. Determine its distance
// from the left/top side of the view as a fraction of the entire image's width/height. Use that percentage
// to calculate the trans in the new view width/height.
//
float percentage = (Math.abs(trans) + (0.5f * prevViewSize)) / prevImageSize;
m[axis] = -((percentage * imageSize) - (viewSize * 0.5f));
}
}
/**
* After rotating, the matrix needs to be translated. This function finds the area of image
* which was previously centered and adjusts translations so that is again the center, post-rotation.
*
* @param axis Matrix.MTRANS_X or Matrix.MTRANS_Y
* @param trans the value of trans in that axis before the rotation
* @param prevImageSize the width/height of the image before the rotation
* @param imageSize width/height of the image after rotation
* @param prevViewSize width/height of view before rotation
* @param viewSize width/height of view after rotation
* @param drawableSize width/height of drawable
*/
private void translateMatrixAfterRotate(int axis, float trans, float prevImageSize, float imageSize, int prevViewSize, int viewSize, int drawableSize) {
if (imageSize < viewSize) {
//
// The width/height of image is less than the view's width/height. Center it.
//
m[axis] = (viewSize - (drawableSize * m[Matrix.MSCALE_X])) * 0.5f;
} else if (trans > 0) {
//
// The image is larger than the view, but was not before rotation. Center it.
//
m[axis] = -((imageSize - viewSize) * 0.5f);
} else {
//
// Find the area of the image which was previously centered in the view. Determine its distance
// from the left/top side of the view as a fraction of the entire image's width/height. Use that percentage
// to calculate the trans in the new view width/height.
//
float percentage = (Math.abs(trans) + (0.5f * prevViewSize)) / prevImageSize;
m[axis] = -((percentage * imageSize) - (viewSize * 0.5f));
}
}
/**
* 获取缩放的中心点。
* @param scale
* @param values
* @return
*/
private PointF getCenter(float scale,float[] values) {
//缩放级别小于原始缩放级别时或者为放大状态时,返回ImageView中心点作为缩放中心点
if(scale*values[Matrix.MSCALE_X]<mScale||scale>=1){
return new PointF(getWidth()/2,getHeight()/2);
}
float cx=getWidth()/2;
float cy=getHeight()/2;
//以ImageView中心点为缩放中心,判断缩放后的图片左边缘是否会离开ImageView左边缘,是的话以左边缘为X轴中心
if((getWidth()/2-values[Matrix.MTRANS_X])*scale<getWidth()/2)
cx=0;
//判断缩放后的右边缘是否会离开ImageView右边缘,是的话以右边缘为X轴中心
if((mImageWidth*values[Matrix.MSCALE_X]+values[Matrix.MTRANS_X])*scale<getWidth())
cx=getWidth();
return new PointF(cx,cy);
}
/**
* android.graphics.Matrixの3x3行列をOpenGLの4x4(列優先)行列に変換する
* (アフィン変換のみ)
* |a11 a12 a13| |0 1 2| |a11 a12 0 a13| |0 4 8 12|
* |a21 a22 a23| |3 4 5| |a21 a22 0 a23| |1 5 9 13|
* |a31 a32 a33| |6 7 8| => | 0 0 1 0| |2 6 10 14|
* |a31 a32 0 a33| |3 7 11 15|
* @param transform
* @param result
* @return
*/
@NonNull
@Size(min=16)
public static float[] toGLMatrix(@NonNull final Matrix transform,
@NonNull @Size(min=16) final float[] result,
@NonNull @Size(min=9) final float[] aMatrix) {
transform.getValues(aMatrix);
result[ 0] = aMatrix[Matrix.MSCALE_X];
result[ 1] = aMatrix[Matrix.MSKEW_Y];
result[ 2] = 0;
result[ 3] = aMatrix[Matrix.MPERSP_0];
result[ 4] = aMatrix[Matrix.MSKEW_X];
result[ 5] = aMatrix[Matrix.MSCALE_Y];
result[ 6] = 0;
result[ 7] = aMatrix[Matrix.MPERSP_1];
result[ 8] = 0;
result[ 9] = 0;
result[10] = 1;
result[11] = 0;
result[12] = aMatrix[Matrix.MTRANS_X];
result[13] = aMatrix[Matrix.MTRANS_Y];
result[14] = 0;
result[15] = aMatrix[Matrix.MPERSP_2];
return result;
}
/**
* After rotating, the matrix needs to be translated. This function finds the area of image
* which was previously centered and adjusts translations so that is again the center, post-rotation.
*
* @param axis Matrix.MTRANS_X or Matrix.MTRANS_Y
* @param trans the value of trans in that axis before the rotation
* @param prevImageSize the width/height of the image before the rotation
* @param imageSize width/height of the image after rotation
* @param prevViewSize width/height of view before rotation
* @param viewSize width/height of view after rotation
* @param drawableSize width/height of drawable
*/
private void translateMatrixAfterRotate(int axis, float trans, float prevImageSize, float imageSize, int prevViewSize, int viewSize, int drawableSize) {
if (imageSize < viewSize) {
//
// The width/height of image is less than the view's width/height. Center it.
//
m[axis] = (viewSize - (drawableSize * m[Matrix.MSCALE_X])) * 0.5f;
} else if (trans > 0) {
//
// The image is larger than the view, but was not before rotation. Center it.
//
m[axis] = -((imageSize - viewSize) * 0.5f);
} else {
//
// Find the area of the image which was previously centered in the view. Determine its distance
// from the left/top side of the view as a fraction of the entire image's width/height. Use that percentage
// to calculate the trans in the new view width/height.
//
float percentage = (Math.abs(trans) + (0.5f * prevViewSize)) / prevImageSize;
m[axis] = -((percentage * imageSize) - (viewSize * 0.5f));
}
}
@Override
public void run() {
float t = (float)(System.currentTimeMillis() - mStartTime) / ZOOM_DURATION;
float interpolateRatio = mInterpolator.getInterpolation(t);
t = (t > 1f) ? 1f : t;
mMatrix.getValues(m);
float newScale = mStartScale + interpolateRatio * (mScale - mStartScale);
float newScaleFactor = newScale / m[Matrix.MSCALE_X];
mMatrix.postScale(newScaleFactor, newScaleFactor, mX, mY);
setImageMatrix(mMatrix);
if (t < 1f) {
post(this);
}
else {
// set exact scale
mMatrix.getValues(m);
mMatrix.setScale(mScale, mScale);
mMatrix.postTranslate(m[Matrix.MTRANS_X], m[Matrix.MTRANS_Y]);
setImageMatrix(mMatrix);
}
}
/**
* 判断是否需要重置
*
* @return 当前缩放级别小于模板缩放级别时,重置
*/
private boolean checkRest() {
// TODO Auto-generated method stub
float[] values = new float[9];
getImageMatrix().getValues(values);
//获取当前X轴缩放级别
float scale = values[Matrix.MSCALE_X];
//获取模板的X轴缩放级别,两者做比较
mMatrix.getValues(values);
return scale < values[Matrix.MSCALE_X];
}
/**
* 和当前矩阵对比,检验dx,使图像移动后不会超出ImageView边界
* @param values
* @param dx
* @return
*/
private float checkDxBound(float[] values,float dx,float dy) {
float width=getWidth();
if(!mLeftDragable&&dx<0){
//加入和y轴的对比,表示在监听到垂直方向的手势时不切换Item
if(Math.abs(dx)*0.4f>Math.abs(dy)&&mFirstMove){
stopDrag();
}
return 0;
}
if(!mRightDragable&&dx>0){
//加入和y轴的对比,表示在监听到垂直方向的手势时不切换Item
if(Math.abs(dx)*0.4f>Math.abs(dy)&&mFirstMove){
stopDrag();
}
return 0;
}
mLeftDragable=true;
mRightDragable=true;
if(mFirstMove) mFirstMove=false;
if(mImageWidth*values[Matrix.MSCALE_X]<width){
return 0;
}
if(values[Matrix.MTRANS_X]+dx>0){
dx=-values[Matrix.MTRANS_X];
}
else if(values[Matrix.MTRANS_X]+dx<-(mImageWidth*values[Matrix.MSCALE_X]-width)){
dx=-(mImageWidth*values[Matrix.MSCALE_X]-width)-values[Matrix.MTRANS_X];
}
return dx;
}
public void syncCharts() {
Matrix srcMatrix;
float[] srcVals = new float[9];
Matrix dstMatrix;
float[] dstVals = new float[9];
// get src chart translation matrix:
srcMatrix = srcChart.getViewPortHandler().getMatrixTouch();
srcMatrix.getValues(srcVals);
// apply X axis scaling and position to dst charts:
for (Chart dstChart : dstCharts) {
dstMatrix = dstChart.getViewPortHandler().getMatrixTouch();
dstMatrix.getValues(dstVals);
dstVals[Matrix.MSCALE_X] = srcVals[Matrix.MSCALE_X];
dstVals[Matrix.MSKEW_X] = srcVals[Matrix.MSKEW_X];
dstVals[Matrix.MTRANS_X] = srcVals[Matrix.MTRANS_X];
dstVals[Matrix.MSKEW_Y] = srcVals[Matrix.MSKEW_Y];
dstVals[Matrix.MSCALE_Y] = srcVals[Matrix.MSCALE_Y];
dstVals[Matrix.MTRANS_Y] = srcVals[Matrix.MTRANS_Y];
dstVals[Matrix.MPERSP_0] = srcVals[Matrix.MPERSP_0];
dstVals[Matrix.MPERSP_1] = srcVals[Matrix.MPERSP_1];
dstVals[Matrix.MPERSP_2] = srcVals[Matrix.MPERSP_2];
dstMatrix.setValues(dstVals);
dstChart.getViewPortHandler().refresh(dstMatrix, dstChart, true);
}
}
/**
* limits the maximum scale and X translation of the given matrix
*
* @param matrix
*/
public void limitTransAndScale(Matrix matrix, RectF content) {
matrix.getValues(matrixBuffer);
float curTransX = matrixBuffer[Matrix.MTRANS_X];
float curScaleX = matrixBuffer[Matrix.MSCALE_X];
float curTransY = matrixBuffer[Matrix.MTRANS_Y];
float curScaleY = matrixBuffer[Matrix.MSCALE_Y];
// min scale-x is 1f
mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX);
// min scale-y is 1f
mScaleY = Math.min(Math.max(mMinScaleY, curScaleY), mMaxScaleY);
float width = 0f;
float height = 0f;
if (content != null) {
width = content.width();
height = content.height();
}
float maxTransX = -width * (mScaleX - 1f);
mTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX);
float maxTransY = height * (mScaleY - 1f);
mTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY);
matrixBuffer[Matrix.MTRANS_X] = mTransX;
matrixBuffer[Matrix.MSCALE_X] = mScaleX;
matrixBuffer[Matrix.MTRANS_Y] = mTransY;
matrixBuffer[Matrix.MSCALE_Y] = mScaleY;
matrix.setValues(matrixBuffer);
}
/**
* 和当前矩阵对比,检验dx,使图像移动后不会超出ImageView边界
*
* @param values
* @param dx
* @return
*/
private float checkDxBound(float[] values, float dx) {
float width = getWidth();
if (mImageWidth * values[Matrix.MSCALE_X] < width)
return 0;
if (values[Matrix.MTRANS_X] + dx > 0)
dx = -values[Matrix.MTRANS_X];
else if (values[Matrix.MTRANS_X] + dx < -(mImageWidth * values[Matrix.MSCALE_X] - width))
dx = -(mImageWidth * values[Matrix.MSCALE_X] - width) - values[Matrix.MTRANS_X];
return dx;
}
/**
* limits the maximum scale and X translation of the given matrix
*
* @param matrix
*/
public void limitTransAndScale(Matrix matrix, RectF content) {
matrix.getValues(matrixBuffer);
float curTransX = matrixBuffer[Matrix.MTRANS_X];
float curScaleX = matrixBuffer[Matrix.MSCALE_X];
float curTransY = matrixBuffer[Matrix.MTRANS_Y];
float curScaleY = matrixBuffer[Matrix.MSCALE_Y];
// min scale-x is 1f
mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX);
// min scale-y is 1f
mScaleY = Math.min(Math.max(mMinScaleY, curScaleY), mMaxScaleY);
float width = 0f;
float height = 0f;
if (content != null) {
width = content.width();
height = content.height();
}
float maxTransX = -width * (mScaleX - 1f);
mTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX);
float maxTransY = height * (mScaleY - 1f);
mTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY);
matrixBuffer[Matrix.MTRANS_X] = mTransX;
matrixBuffer[Matrix.MSCALE_X] = mScaleX;
matrixBuffer[Matrix.MTRANS_Y] = mTransY;
matrixBuffer[Matrix.MSCALE_Y] = mScaleY;
matrix.setValues(matrixBuffer);
}
/**
* スキューを考慮して実際の拡大縮小率を取得する
* @param mat
* @return
*/
public static float getScale(@NonNull final float[] mat) {
final float scaleX = mat[Matrix.MSCALE_X];
final float skewY = mat[Matrix.MSKEW_Y];
return (float) Math.sqrt(scaleX * scaleX + skewY * skewY);
}
/** Gets the current scale factor. */
@Override
public float getScaleFactor() {
mActiveTransform.getValues(mTempValues);
return mTempValues[Matrix.MSCALE_X];
}
/**
* 获得当前的缩放比例
*/
public final float getScale() {
matrix.getValues(matrixValues);
return matrixValues[Matrix.MSCALE_X];
}
/** Gets the current scale factor. */
@Override
public float getScaleFactor() {
mActiveTransform.getValues(mTempValues);
return mTempValues[Matrix.MSCALE_X];
}
@Override
protected void onDraw(Canvas canvas) {
if (mBitmap != null) {
float[] arrayOfFloat = new float[9];
matrix.getValues(arrayOfFloat);
float f1 = 0.0F * arrayOfFloat[0] + 0.0F * arrayOfFloat[1] + arrayOfFloat[2];
float f2 = 0.0F * arrayOfFloat[3] + 0.0F * arrayOfFloat[4] + arrayOfFloat[5];
float f3 = arrayOfFloat[0] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat[1] + arrayOfFloat[2];
float f4 = arrayOfFloat[3] * this.mBitmap.getWidth() + 0.0F * arrayOfFloat[4] + arrayOfFloat[5];
float f5 = 0.0F * arrayOfFloat[0] + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2];
float f6 = 0.0F * arrayOfFloat[3] + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5];
float f7 = arrayOfFloat[0] * this.mBitmap.getWidth() + arrayOfFloat[1] * this.mBitmap.getHeight() + arrayOfFloat[2];
float f8 = arrayOfFloat[3] * this.mBitmap.getWidth() + arrayOfFloat[4] * this.mBitmap.getHeight() + arrayOfFloat[5];
canvas.save();
//先往文字上绘图
mBitmap = originBitmap.copy(Bitmap.Config.ARGB_8888, true);
canvasText.setBitmap(mBitmap);
canvasText.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
float left = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, dm);
float scalex = arrayOfFloat[Matrix.MSCALE_X];
float skewy = arrayOfFloat[Matrix.MSKEW_Y];
float rScale = (float) Math.sqrt(scalex * scalex + skewy * skewy);
float size = rScale * 0.75f * mDefultSize;
if (size > mMaxFontSize) {
mFontSize = mMaxFontSize;
} else if (size < mMinFontSize) {
mFontSize = mMinFontSize;
} else {
mFontSize = size;
}
mFontPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mFontSize, dm));
String[] texts = autoSplit(mStr, mFontPaint, mBitmap.getWidth() - left * 3);
float height = (texts.length * (baseline + fm.leading) + baseline);
float top = (mBitmap.getHeight() - height) / 2;
//基于底线开始画的
top += baseline;
for (String text : texts) {
if (TextUtils.isEmpty(text)) {
continue;
}
canvasText.drawText(text, mBitmap.getWidth() / 2, top, mFontPaint); //坐标以控件左上角为原点
top += baseline + fm.leading; //添加字体行间距
}
canvas.drawBitmap(mBitmap, matrix, null);
//删除在右上角
dst_delete.left = (int) (f3 - deleteBitmapWidth / 2);
dst_delete.right = (int) (f3 + deleteBitmapWidth / 2);
dst_delete.top = (int) (f4 - deleteBitmapHeight / 2);
dst_delete.bottom = (int) (f4 + deleteBitmapHeight / 2);
//拉伸等操作在右下角
dst_resize.left = (int) (f7 - resizeBitmapWidth / 2);
dst_resize.right = (int) (f7 + resizeBitmapWidth / 2);
dst_resize.top = (int) (f8 - resizeBitmapHeight / 2);
dst_resize.bottom = (int) (f8 + resizeBitmapHeight / 2);
//置顶在左上角
dst_top.left = (int) (f1 - topBitmapWidth / 2);
dst_top.right = (int) (f1 + topBitmapWidth / 2);
dst_top.top = (int) (f2 - topBitmapHeight / 2);
dst_top.bottom = (int) (f2 + topBitmapHeight / 2);
//水平镜像在右下角
// dst_flipV.left = (int) (f5 - topBitmapWidth / 2);
// dst_flipV.right = (int) (f5 + topBitmapWidth / 2);
// dst_flipV.top = (int) (f6 - topBitmapHeight / 2);
// dst_flipV.bottom = (int) (f6 + topBitmapHeight / 2);
if (isInEdit) {
canvas.drawLine(f1, f2, f3, f4, localPaint);
canvas.drawLine(f3, f4, f7, f8, localPaint);
canvas.drawLine(f5, f6, f7, f8, localPaint);
canvas.drawLine(f5, f6, f1, f2, localPaint);
canvas.drawBitmap(deleteBitmap, null, dst_delete, null);
canvas.drawBitmap(resizeBitmap, null, dst_resize, null);
// canvas.drawBitmap(flipVBitmap, null, dst_flipV, null);
canvas.drawBitmap(topBitmap, null, dst_top, null);
}
canvas.restore();
}
}
private float getMatrixScaleX() {
matrix.getValues(m);
return m[Matrix.MSCALE_X];
}
/**
* <p>Performs a zoom out animation so that the image entirely fits within the view using centerpoint coordinates.</p>
* @param duration
* @param x
* @param y
*/
public void animateZoomOutToFit(long duration, float x, float y) {
float sx = corrector.getValues()[Matrix.MSCALE_X];
animateZoom(sx, corrector.getInnerFitScale(), duration, new ScaleAnimatorHandler(corrector, x, y), null);
}
/**
* Returns the current scale value
*
* @return float - current scale value
*/
public final float getScale() {
suppMatrix.getValues(matrixValues);
return matrixValues[Matrix.MSCALE_X];
}