Android图片处理:PinchImageView源码解析

本文详细分析了Android中的PinchImageView组件,包括双击放大/缩小实现,惯性滑动(Fling)的处理,以及双指缩放和单指移动的逻辑。双击事件通过获取双击点并调整图片缩放,惯性滑动通过自定义衰减算法。双指缩放依赖于外部和内部变换矩阵,单指移动则涉及图片边界矫正。
摘要由CSDN通过智能技术生成

PinchImageView 使用 GestureDetector 来处理长按、点击、双击、惯性滑动事件,在 onTouchEvent 里处理双指缩放和单指移动等事件。 里面有两个矩阵,一个是外部变换矩阵(mOuterMatrix),主要记录手势操作的结果,一个是内部变换矩阵(getInnerMatrix(Matrix)),就是根据 fitCenter 等缩放模式进行缩放平移后的初始矩阵。这里区分两个矩阵可能是借鉴了PhotoView的经验,手势操作和原始缩放互不影响,手势操作后最终的缩放只需要两个矩阵相乘就好了。 下面的代码分析不一定会完全贴源码,有的是经过稍微改动的。

1 双击、惯性滑动

长按和点击就是调用回调,我们主要来看双击和惯性滑动。

1.1 双击

PinchImageView 只做了一级的放大缩小 ,就是说只能在最大和初始缩放值之间切换。 基本原理:捕获双击事件,拿到双击点的x、y坐标,对图片进行缩放变换,将双击点位置移动到视图中间。 代码较长,我们一点点拆分。 这里要先介绍下 PinchImageView 的对象池(ObjectsPool)。 ObjectsPool 维护一个对象队列,在容量范围内可以循环复用对象。大致使用流程如下图所示:

  1. 在队列里获取 innerMatrix 对象(take()),队列为空则新建一个对象返回,否则出队一个对象重置后返回。
  2. 在队列里获取 targetMatrix 对象。
  3. 使用完 targetMatrix 归还(given(obj))。
  4. 使用完 innerMatrix 归还。

归还顺序无所谓。

/**
 * 对象池
 *
 * 防止频繁new对象产生内存抖动.
 * 由于对象池最大长度限制,如果吞吐量超过对象池容量,仍然会发生抖动.
 * 此时需要增大对象池容量,但是会占用更多内存.
 *
 * @param <T> 对象池容纳的对象类型
 */
private static abstract class ObjectsPool<T> {
    /**
     * 对象池的最大容量
     */
    private int mSize;
    /**
     * 对象池队列
     */
    private Queue<T> mQueue;

    public ObjectsPool(int size) {
        mSize = size;
        mQueue = new LinkedList<T>();
    }

    public T take() {
        //如果池内为空就创建一个
        if (mQueue.size() == 0) {
            return newInstance();
        } else {
            //对象池里有就从顶端拿出来一个返回
            return resetInstance(mQueue.poll());
        }
    }
    public void given(T obj) {
        //如果对象池还有空位子就归还对象
        if (obj != null && mQueue.size() < mSize) {
            mQueue.offer(obj);
        }
    }

    abstract protected T newInstance();

    abstract protected T resetInstance(T obj);
}

继续看双击事件的处理。

private void doubleTap(float x, float y) {
    //获取第一层变换矩阵
    Matrix innerMatrix = MathUtils.matrixTake();
    getInnerMatrix(innerMatrix);

    ……
    MathUtils.matrixGiven(innerMatrix);
}

首先是获取内部变换矩阵。MathUtils.matrixTake() 是从 Matrix 对象池(MatrixPool)里获取一个 Matrix 对象。

public static Matrix matrixTake() {
    return mMatrixPool.take();
}
/**
 * 获取某个矩阵的copy
 */
public static Matrix matrixTake(Matrix matrix) {
    Matrix result = mMatrixPool.take();
    if (m
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值