想实现一个缩放图片的效果,是那种两指触摸滑动缩放的。我并没有去重新ImageView
而是重写了View
然后 调用canvas.drawBitmap
的方法,然后通过matrix
去实现缩放效果的。(重写ImageView
会更麻烦的)这里的实现比较简单。
代码如下:
public class ScaleImage extends BaseView {
private Matrix matrix;
private Bitmap bitmap;
private Paint paint;
private int fingerSize = 0;
private float downX0;
private float downY0;
private float downX1;
private float downY1;
public ScaleImage(Context context) {
super(context);
}
public ScaleImage(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ScaleImage(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ScaleImage(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
paint = new Paint();
paint.setAntiAlias(true);
matrix = new Matrix();
Bitmap temp = BitmapFactory.decodeResource(getResources(), R.drawable.yellow);
int bw = temp.getWidth();
int bh = temp.getHeight();
float scale = Math.min(1f * mWidth / bw, 1f * mHeight / bh);
LogUtils.w("scale==" + scale);
bitmap = scaleBitmap(temp, scale);
// compute init left, top
int bbw = bitmap.getWidth();
int bbh = bitmap.getHeight();
Point center = new Point(mWidth / 2, mHeight / 2);
Point bmpCenter = new Point(bbw / 2, bbh / 2); // 图片原来的中心点
// matrix.postScale(0.9f, 0.9f, center.x, center.y); // 中心点参数是有用的
matrix.postTranslate(center.x - bmpCenter.x, center.y - bmpCenter.y); // 移动到当前view 的中心
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap, matrix, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// todo: event.getPointerCount() 这个值并不准确,第一个离开的手指没有去计算!
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
fingerSize = 1;
LogUtils.i("当前手指数量:" + fingerSize);
downX0 = event.getX(0);
downY0 = event.getY(0);
break;
case MotionEvent.ACTION_MOVE:
if (fingerSize >= 2) {
// 计算两指触摸到的时候,中心点的位置
float center2x = downX0 + (downX1 - downX0) / 2;
float center2y = downX0 + (downX1 - downX0) / 2;
float x0 = event.getX(0);
float y0 = event.getY(0);
float x1 = event.getX(1);
float y1 = event.getY(1);
// 缩放比例:移动后的两点距离 / 移动前的两点距离
float scaleX = distance(x0, y0, x1, y1) / distance(downX0, downY0, downX1, downY1);
LogUtils.w("缩放比例:" + scaleX);
if (Math.abs(scaleX) <= 2) {
matrix.postScale(scaleX, scaleX, center2x, center2y);
}
downX0 = x0;
downY0 = y0;
downX1 = x1;
downY1 = y1;
} else if (fingerSize == 1) {
// 移动图片
float x0 = event.getX(0);
float y0 = event.getY(0);
float dx = x0 - downX0;
float dy = y0 - downY0;
matrix.postTranslate(dx, dy);
downX0 = x0;
downY0 = y0;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
fingerSize += 1;
LogUtils.i("当前手指数量:" + event.getPointerCount());
if (fingerSize == 2) {
downX1 = event.getX(0);
downY1 = event.getY(0);
}
break;
case MotionEvent.ACTION_POINTER_UP:
fingerSize -= 1;
LogUtils.i("当前手指数量:" + event.getPointerCount());
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
fingerSize = 0;
LogUtils.i("当前手指数量:" + event.getPointerCount());
break;
}
postInvalidate();
return true;
}
private float distance(float x1, float y1, float x2, float y2) {
float dx = x2 - x1;
float dy = y2 - y1;
return (float) Math.pow(dx * dx + dy * dy, 0.5);
}
/**
* 根据给定的宽和高进行拉伸
*
* @param origin 原图
* @param scale 缩放比例
* @return new Bitmap
*/
private Bitmap scaleBitmap(Bitmap origin, float scale) {
if (origin == null) {
return null;
}
int height = origin.getHeight();
int width = origin.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);// 使用后乘
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (!origin.isRecycled()) {
origin.recycle();
}
return newBM;
}
}
由于这个需要动图才能看到效果,我就不上图了。
以上,就实现了单指移动,双指缩放的效果了。~
参考资料:
安卓–多指触控
getAction、getActionMask、getActionIndex区别
安卓开发——MotionEvent中getAction、getActionMask、getActionIndex区别