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

自定义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);});
复制代码

完整代码见这里。

转载于:https://juejin.im/post/5cc57edce51d456e266d89b0

使用RxJava实现ImageView的拖动、旋转和缩放相关推荐

  1. android 点击图片旋转90度,Android UI之ImageView实现图片旋转和缩放

    这一篇,给大家介绍一下ImageView控件的使用,ImageView主要是用来显示图片,可以对图片进行放大.缩小.旋转的功能. android:sacleType属性指定ImageVIew控件显示图 ...

  2. openlayers拖拽、旋转、缩放、拉伸变形 (十二)

    gis应用中拖动旋转和缩放是编辑中比较常见的功能,在openlayers中拖拽可以通过ol.interaction.Translate来实现,但是其他功能没有,所以要用的openlayers的一个扩展 ...

  3. android-ImageView的拖动、旋转、缩放、边界回弹、双击缩放、单击销毁及源码下载

    博客地址:http://blog.csdn.net/u010156024 TouchImageViewActivity 是本人一句一句代码写的,参考了网上大牛的博客. 不过其中的效果是网上没有的,也是 ...

  4. Android 视频旋转、缩放与回弹动效实现(二)

    文章目录 Android 视频旋转.缩放与回弹动效实现(二) 功能需求 实现思路 1. 旋转识别 旋转识别:RotateGestureDetector 2. 旋转处理 旋转处理:VideoTouchR ...

  5. RuntimeTransformGizmo:位移、旋转、缩放插件

    写在前面:本文主要讲述插件的API,相关的基础操作,本站有相关的帖子,请自行搜索学习: PS:本文中的所有示例均来自插件的官方文档,如有不清楚或者不理解的地方可以去翻一下文档 插件下载地址:点此下载 ...

  6. 【计算机图形学】c++ OpenGL 二维变换(包括多边形绘制、平移、旋转及缩放)

    运行结果演示 源代码 // 二维变换.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include<GL/glut.h> #i ...

  7. Unity Camera围绕物体旋转和缩放简单实现

    想实现Camera围绕物体旋转和缩放这个功能,我们第一时间想到的就是RotateAround()方法但是使用该方法就面临着一个问题,当你鼠标横着拖动屏幕使相机围绕物体旋转90度后,在竖着拖动时会发现相 ...

  8. tinkerCAD入门操作(2):移动、旋转和缩放对象

    tinkerCAD入门操作:移动.旋转和缩放对象 介绍 现在您已经学会了如何在工作平面上旋转,是时候真正开始处理对象了. 在本课中,您将了解有关对象物理属性的更多信息. 放置一个盒子 我们需要一个对象 ...

  9. 二维图形学的变换-平移、旋转、缩放 OpenGL

    这里实现的是多点画多边形,然后把这个多边形进行二维的变换. 首先,多点画多边形,为了方便起见,我直接调用了Opengl的库函数.其次,就是如何进行多边形的二维变换.在这里我有两种方法.第一种是直接根据 ...

最新文章

  1. Centos调出图形化的网络管理
  2. 构建之法之单元测试及设计流程
  3. python中顺序查找法例子_Python查找算法(一)------ 顺序查找
  4. Javascript模板引擎handlebars使用实例及技巧
  5. c远程连接mysql数据库_MySQL数据库远程连接开启方法
  6. PhpStorm调用浏览器运行php文件
  7. 40vf什么意思_变频器的VF模式是什么意思?VF什么意思
  8. android系统自动休眠代码流程,android系统休眠与唤醒驱动流程详细分析.doc
  9. vb.net使用DirectX入门知识
  10. 【渝粤题库】陕西师范大学200941小学数学教学论 作业(高起专)
  11. 网站木马检测_检测病毒,用这几个网站就够了
  12. linux git ssh目录权限,Git SSH Key的配置问题
  13. 基于java的婚恋交友动态网站
  14. 知名互联网公司都在使用哪些数据库
  15. 解决问题——无法连接到更新服务器。我们将稍后再试,你也可以立即进行检查。如果问题仍然存在,请确保你已连接到Internet
  16. ios10之后的一些新特性
  17. error: src refspec master does not match any. 错误的解决办法
  18. 计算机组成原理~计算机系统简介①
  19. 微信公众平台开发入门视频教程已发布
  20. 什么是HTML和CSS

热门文章

  1. linux安装IPython四种方法
  2. 解除织梦dedeCMS标题/关键词/ 简略标题长度限制听语音
  3. linux下重命名脚本推荐
  4. Scalaz(12)- Monad:再述述flatMap,顺便了解MonadPlus
  5. 【轉】Android编程之SparseArrayE详解
  6. lnmp安装博客系统WordPress
  7. Android调用WebService系列之对象构建传递
  8. MySQL实时复制成为可能?
  9. iOS Swift编程语言
  10. JSONObject JSONArray各种用法以及js eval()函数与JSON.parse的区