自定义 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 加入
我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。











评论