内容简介:本文介绍一种使用Rxjava实现图片交互操作的方法。支持单指拖动,双指旋转缩放,效果如下:首先自定义用
本文介绍一种使用Rxjava实现图片交互操作的方法。支持单指拖动,双指旋转缩放,效果如下:
自定义View
首先自定义 TrsImageView
继承 ImageView
,设置 ScaleType
为 Matrix
,我们使用矩阵计算最终的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的拖动、旋转和缩放》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Testing Flutter apps翻译-点击,拖动和输入文本
- ios – 我正在使用XCode 7和Swift,我的控制拖动动作不起作用
- 探讨把一个元素从它所在的div 拖动到另一个div内的实现方法
- [译] 为什么要做特征缩放,怎么做特征缩放,什么时候做特征缩放?特征缩放三连了解一下
- golang使用nfnt缩放图片
- 特征工程之特征缩放 & 特征编码
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。