实现自定义拖拽、放大的imageview

2020-05-20  本文已影响0人  阿里高级软件架构师

这种控件很简单,基本上没什么难度,无非就是onTouch事件的处理:

我们先从简单的做起,实现自定义拖拽:

首先,你移动的过程中,你得记录一下你刚开始的位置,然后你移动完成后,需要记录一下终点,至于这个距离如何记录,onTouch正好给你API去获取移动的距离,然后学过数学的都知道,一个手机屏幕是一个二维坐标系统,你都知道了起点,知道了终点,然后你做一下加法,不就出来了。

getImageMatrix()你先获取手机屏幕的矩阵元素,然后通过MotionEvent获取起点的坐标,如下图所示:

然后你移动,产生距离,那距离就来搞一下下啊,你往前,就用终点减去起点,就是移动距离,你既然获得距离了,就来移动啊!

postTranslate(),使用这个方法就可以实现移动的功能了。

        然后接下来就得实现缩小放大的功能;一般你放大是不是得两根手指头,那触摸点是不是就得有两个了,那你如何获取放大的倍数?我给你一个思路:你手指动了,你是不是会产生缩放距离,同时在X或者Y轴或者同时,那你就会有一个产生的缩放距离,在X轴和Y轴上的,你都知道了X和Y的距离了,那来一个勾股定理,是不是就得算出来了斜边的距离,因为你动手指,产生了距离,不管你移动了多少,斜边都会产生移动。那你用初始的斜边长度去除以手势在屏幕上移动后产生的斜边长度,结果就是缩放的比例大小。这个比例你获取到了,但是你是不是得有一个缩放点,就是你根据哪个点进行缩放的,我们一般取缩放后的中间点,如果你取起点,那就是反向了,取终点,就缩放不正常,会产生二倍放大,这个是线性代数里面的一个基本的知识。然后你用postScale()方法进行缩放,第一个是X轴的缩放,第二个是Y轴的缩放,然后后面两个是中点,中间点就是你两个手指的中间点。思路都出来了,代码就出来了:

package com.ireader.plug.testapplication;

import android.content.Context;

import android.graphics.Matrix;

import android.graphics.PointF;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.widget.ImageView;

public class BaseDragZoomImageViewextends ImageViewimplements View.OnTouchListener{

  private int mode =0;

  private static final int MODE_DRAG =1;

  private static final int MODE_ZOOM =2;

  private PointFstartPoint =new PointF();

  private Matrixmatrix =new Matrix();

  private MatrixcurrentMatrix =new Matrix();

  private float startDis;

  private PointFmidPoint;

  public BaseDragZoomImageView(Context context, AttributeSet attrs, int defStyle)

{

    super(context, attrs, defStyle);

    setOnTouchListener(this);

  }

  public BaseDragZoomImageView(Context context, AttributeSet attrs)

{

    this(context, attrs, 0);

    setOnTouchListener(this);

  }

  public BaseDragZoomImageView(Context context)

{

    this(context, null);

    setOnTouchListener(this);

  }

  @Override

  public boolean onTouch(View v, MotionEvent event) {

    switch (event.getAction() & MotionEvent.ACTION_MASK) {

      case MotionEvent.ACTION_DOWN:

        mode = MODE_DRAG;

        currentMatrix.set(getImageMatrix());

        startPoint.set(event.getX(), event.getY());

break;

      // 手指在屏幕上移动,改事件会被不断触发

      case MotionEvent.ACTION_MOVE:

        if (mode == MODE_DRAG) {

          float dx = event.getX() - startPoint.x;

          float dy = event.getY() - startPoint.y;

          matrix.set(currentMatrix);

          matrix.postTranslate(dx, dy);

        }

        else if (mode == MODE_ZOOM) {

          float endDis = distance(event);

          if (endDis > 10f) {

            float scale = endDis / startDis;

            matrix.set(currentMatrix);

            matrix.postScale(scale, scale,midPoint.x,midPoint.y);

          }

}

        break;

      case MotionEvent.ACTION_UP:

      case MotionEvent.ACTION_POINTER_UP:

        mode = 0;

break;

      case MotionEvent.ACTION_POINTER_DOWN:

        mode = MODE_ZOOM;

        startDis = distance(event);

        if (startDis > 10f) {

          midPoint = mid(event);

          currentMatrix.set(getImageMatrix());

        }

        break;

    }

setImageMatrix(matrix);

return true;

  }

  private float distance(MotionEvent event) {

    float dx = event.getX(1) - event.getX(0);

    float dy = event.getY(1) - event.getY(0);

    return (float) Math.sqrt(dx * dx + dy * dy);

  }

  private PointFmid(MotionEvent event) {

    float midX =(event.getX(1) + event.getX(0)) /2;

    float midY =(event.getY(1) + event.getY(0)) /2;

    return new PointF(midX, midY);

  }

}

上一篇下一篇

猜你喜欢

热点阅读