写点什么

自定义 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
用户头像

Changing Lin

关注

获得机遇的手段远超于固有常规之上~ 2020.04.29 加入

我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。

评论

发布
暂无评论
自定义View:如何实现一个放大缩小的图片控件