自定义 View:如何实现一个放大缩小的图片控件
作者:Changing Lin
- 2021 年 11 月 11 日
本文字数:2294 字
阅读完需:约 8 分钟
1.知识点
自定义 View 绘制图像
属性动画
手势检测
各种事件接口的含义
2.原理
重写 View.onDraw 方法,调用 Canvas.drawBitmap 方法,在指定位置绘制图像
属性动画,用于平滑的过渡放大和缩小
使用 GestureDetectorCompat 类来实现对手势的检测,兼容各种系统版本的处理
重写 View.onTouchEvent 方法,把触摸事件分发给 GestureDetectorCompat.onTouchEvent 处理
重写 GestureDetectorCompat.onDown 方法,修改返回值为 true,表示 GestureDetectorCompat 处理后续 MotionEvent。
重写 GestureDetectorCompat.onDoubleTap 方法,来处理用户的双击事件,改变放大缩小倍数。
3.代码
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.view.GestureDetectorCompat;
public class ScalableImageView extends View implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
public static final String TAG = "ScalableImageView";
public static final float IMAGE_WIDTH = Util.dp2px(300); // 指定图片的尺寸
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Bitmap bitmap;
float offsetX;
float offsetY;
float smallScale;
float bigScale;
float curScale = 0f;
ObjectAnimator objectAnimator;
GestureDetectorCompat detector;
{
bitmap = Util.getAvatar(getResources(), (int) IMAGE_WIDTH, R.drawable.audi);
}
public ScalableImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
detector = new GestureDetectorCompat(context, this);
}
public void setCurScale(float curScale) {
this.curScale = curScale;
Log.e(TAG, "setCurScale: " + this.curScale);
invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
offsetX = (getWidth() - bitmap.getWidth()) / 2.0f;
offsetY = (getHeight() - bitmap.getHeight()) / 2.0f;
if ((float) bitmap.getWidth() / bitmap.getHeight() > (float) getWidth() / getHeight()) {
smallScale = (float) getWidth() / bitmap.getWidth();
bigScale = (float) getHeight() / bitmap.getHeight();
} else {
smallScale = (float) getHeight() / bitmap.getHeight();
bigScale = (float) getWidth() / bitmap.getWidth();
}
objectAnimator = ObjectAnimator.ofFloat(this, "curScale", 0, smallScale, bigScale);
objectAnimator.setStartDelay(500);
objectAnimator.setDuration(1000);
objectAnimator.start();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (null != objectAnimator) objectAnimator.cancel();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.scale(curScale, curScale, getWidth() / 2, getHeight() / 2);
canvas.drawBitmap(bitmap, offsetX, offsetY, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return detector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
Log.e(TAG, "onDown: "+e);
return true;
}
@Override
public void onShowPress(MotionEvent e) {
Log.e(TAG, "onShowPress: "+e);
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.e(TAG, "onSingleTapUp: "+e);
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.e(TAG, "onScroll: "+distanceX);
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Log.e(TAG, "onLongPress: "+e);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.e(TAG, "onFling: "+velocityX);
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.e(TAG, "onSingleTapConfirmed: "+e);
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.e(TAG, "onDoubleTap: "+e);
setCurScale(curScale == smallScale? bigScale: smallScale);
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
Log.e(TAG, "onDoubleTapEvent: "+e);
return false;
}
}
复制代码
划线
评论
复制
发布于: 55 分钟前阅读数: 3
版权声明: 本文为 InfoQ 作者【Changing Lin】的原创文章。
原文链接:【http://xie.infoq.cn/article/3f9fc07dae9ea0a610f4c37c4】。文章转载请联系作者。
Changing Lin
关注
获得机遇的手段远超于固有常规之上~ 2020.04.29 加入
我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。
评论