使用RxJava实现ImageView的拖动、旋转和缩放

栏目: Java · 发布时间: 5年前

内容简介:本文介绍一种使用Rxjava实现图片交互操作的方法。支持单指拖动,双指旋转缩放,效果如下:首先自定义用

本文介绍一种使用Rxjava实现图片交互操作的方法。支持单指拖动,双指旋转缩放,效果如下:

使用RxJava实现ImageView的拖动、旋转和缩放

自定义View

首先自定义 TrsImageView 继承 ImageView ,设置 ScaleTypeMatrix ,我们使用矩阵计算最终的translate, rotate和scale。

public class TrsImageView extends ImageView {

    public TrsImageView(Context context) {
        super(context);
        init();
    }
    
    private void init() {
        Matrix matrix = new Matrix();
        setScaleType(ScaleType.MATRIX);
        setImageMatrix(matrix);
    }
}
复制代码

创建touch事件Observable

create 方法创建 Observable ,只考虑单指和双指的情况,用 share 操作符使 Observable 可以被多次订阅。自定义 Event 类,保存触摸事件id和位置。

private void init() {
        ...
        Observable<Event> touchStream = Observable.create((ObservableEmitter<Event> emitter) -> {
            setOnTouchListener((v, event) -> {
                int pointerCount = event.getPointerCount();
                if (pointerCount == 1) {
                    Event e = new Event();
                    e.action = event.getActionMasked();
                    e.p1 = new Vector(event.getX(), event.getY());
                    emitter.onNext(e);
                } else if (pointerCount == 2) {
                    Event e = new Event();
                    e.action = event.getActionMasked();
                    e.p1 = new Vector(event.getX(0), event.getY(0));
                    e.p2 = new Vector(event.getX(1), event.getY(1));
                    emitter.onNext(e);
                }
                return true;
            });
        }).share();
    }
复制代码

使用 filter 操作符获取不同触摸事件的Observable

private void init() {
        ...
        Observable<Event> pointer1Down = touchStream.filter(e -> e.action == MotionEvent.ACTION_DOWN);
        Observable<Event> pointer2Down = touchStream.filter(e -> e.action == MotionEvent.ACTION_POINTER_DOWN);
        Observable<Event> pointerMove = touchStream.filter(e -> e.action == MotionEvent.ACTION_MOVE);
        Observable<Event> pointer2Up = touchStream.filter(e -> e.action == MotionEvent.ACTION_POINTER_UP);
        Observable<Event> pointer1Up = touchStream.filter(e -> e.action == MotionEvent.ACTION_UP);
    }
复制代码

计算位移、旋转和缩放

首先考虑单指拖动的操作流程:

手指按下 -> 手指移动 -> 手指抬起
复制代码

我们用两次相邻的 手指移动 的位移去移动图片,计算方法如下:

Observable<Vector> delta1 = Observable.combineLatest(pointerMove, pointerMove.skip(1), (prev, cur) -> prev.p1.subtract(cur.p1));
复制代码

完整流程代码如下:

pointer1Down
        .flatMap(e -> delta1.takeUntil(pointer1Up))
        .subscribe(v -> {
            matrix.postTranslate(v.x, v.y);
            setImageMatrix(matrix);
        });
复制代码

再来考虑双指操作流程:

第二个手指按下 -> 手指移动 -> 第二个手指抬起
复制代码

同样,我们用两次相邻的 手指移动 计算图片的位移、旋转和缩放,定义类 Delta 保存这些值

Observable<Delta> delta2 = Observable.combineLatest(pointerMove, pointerMove.skip(1), (prev, cur) -> {
    Delta delta = new Delta();
    delta.center = cur.center();
    delta.translate = prev.center().subtract(cur.center());
    delta.scale = prev.length() / cur.length();
    delta.rotate = cur.vector().angle(prev.vector());
    return delta;
});
复制代码

完整流程代码如下:

pointer2Down
        .flatMap(e -> delta2.takeUntil(pointer2Up))
        .subscribe(d -> {
            matrix.postTranslate(d.translate.x, d.translate.y);
            matrix.postRotate(d.rotate, d.center.x, d.center.y);
            matrix.postScale(d.scale, d.scale, d.center.x, d.center.y);
            setImageMatrix(matrix);
        });
复制代码

第二个手指按下的时候,单指拖动流程应该停止,第二个手指抬起的时候,单指拖动流程应该重新开始。所以我们需要修改单指拖动流程的实现:

pointer1Down
        .mergeWith(pointer2Up)
        .flatMap(e -> delta1.takeUntil(pointer1Up).takeUntil(pointer2Down))
        .subscribe(v -> {
            matrix.postTranslate(v.x, v.y);
            setImageMatrix(matrix);
        });
复制代码

完整代码见 这里


以上所述就是小编给大家介绍的《使用RxJava实现ImageView的拖动、旋转和缩放》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

世界因你不同

世界因你不同

李开复、范海涛 / 中信出版社 / 2009-9 / 29.80元

这是李开复唯一的一本自传,字里行间,是岁月流逝中沉淀下来的宝贵的人生智慧和职场经验。捣蛋的“小皇帝”,11岁的“留学生”,奥巴马的大学同学,26岁的副教授,33岁的苹果副总裁,谷歌中国的创始人,他有着太多传奇的经历,为了他,两家最大的IT公司对簿公堂。而他的每一次人生选择,都是一次成功的自我超越。 透过这本自传,李开复真诚讲述了他鲜为人知的成长史、风雨兼程的成功史和烛照人生的心灵史,也首次全......一起来看看 《世界因你不同》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具