首页 > 编程语言 >骚操作:使用RxJava实现ImageView的拖动、旋转和缩放

骚操作:使用RxJava实现ImageView的拖动、旋转和缩放

时间:2023-08-19 11:34:29浏览次数:49  
标签:Observable matrix 缩放 cur new RxJava ImageView event center

本文介绍一种使用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);
        });

最后给大家分享一套由阿里高级架构师编写的《Android八大模块进阶资料》,帮助大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。


这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶资料》,帮助大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

Android八大模块进阶 https://docs.qq.com/doc/DUktJeUtCRVFBbXpB


《Android八大模块进阶笔记》

骚操作:使用RxJava实现ImageView的拖动、旋转和缩放_Android_02

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、源码解析合集

骚操作:使用RxJava实现ImageView的拖动、旋转和缩放_缩放_03

二、开源框架合集

骚操作:使用RxJava实现ImageView的拖动、旋转和缩放_自定义_04


标签:Observable,matrix,缩放,cur,new,RxJava,ImageView,event,center
From: https://blog.51cto.com/u_16175637/7147787

相关文章

  • Maui Blazor 安卓文字随系统文字缩放问题解决
    MauiBlazor的文字在正常情况下会随着用户手机内的系统文字设置大小而变化,所以可能导致手机应用内APP的布局由于文字变得过大或者过小而错乱。可以通过设置Webview里的文字缩放,保持应用内文字大小不变,代码如下:1.首先在Mainpage.xaml里设置好初始化事件,BlazorWebViewInitialize......
  • Android Rxjava :最简单&全面背压讲解 (Flowable)
    1.前言Rxjava背压:被观察者发送事件的速度大于观察者接收事件的速度时,观察者内会创建一个无限制大少的缓冲池存储未接收的事件,因此当存储的事件越来越多时就会导致OOM的出现。(注:当subscribeOn与observeOn不为同一个线程时,被观察者与观察者内存在不同时长耗时任务,就会使发送与接收速......
  • VTK 实例20:用vtkImageViewer2显示三维医学图像mhd的某个切面
    1#include"vtkAutoInit.h"2VTK_MODULE_INIT(vtkRenderingOpenGL2);3VTK_MODULE_INIT(vtkInteractionStyle);45#include<vtkSmartPointer.h>6#include<vtkImageViewer2.h>7#include<vtkRenderWindow.h>8#include<......
  • Android使用Rxjava获取本地存储的txt文件
    废话不多说,直接上代码:publicclassReadLocalFileActivityextendsAppCompatActivity{privateListViewlistView;privateList<File>files=newArrayList<>();privateArrayAdapteradapter;@OverrideprotectedvoidonCreate(@Nullab......
  • Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
    仿照微信,朋友圈分享图片功能。可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片。很不错的源码,大家有需要可以下载看看。微信微信微信微信下载地址: 微信上传图片源码很多网友不知道怎么获取图片路径,这里贴出......
  • Flutter 可以缩放拖拽的图片
    在pub上面找了下,没有发现一个效果跟微信一样的支持缩放拖拽效果的image,所以就自己撸了一个,之前写过Flutter什么功能都有的Image,于是就在这个上面新增了这个功能。主要功能:缩放拖拽在PageView里面缩放拖拽支持缩放拖拽image用法1.将extended_image的mode参数设置为ExtendedImageMod......
  • ChatGPT 问答00007 RxJava介绍
    RxJava是一个基于反应式编程的库,它提供了一套丰富的操作符和数据类型,用于处理异步和事件驱动的编程。它是ReactiveX的Java版本实现,旨在简化异步和并发编程,并提供响应式流式处理的能力。RxJava的核心组件包括以下几个部分:Observable(可观察者):代表一个可被观察的数据流。它......
  • ChatGPT 问答00008 RxJava 使用案例
    RxJava可以应用于各种异步和事件驱动的编程场景。以下是一些RxJava的使用案例:网络请求:使用RxJava可以方便地处理网络请求和响应。你可以使用Retrofit或者其他网络库来发送异步请求,并将其封装为Observable,然后通过操作符进行转换、过滤和合并等操作,最后将结果交给观察者......
  • 深入浅出RxJava (四:在Android中使用响应式编程)
    [url=http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/]原文链接[/url]在第1,2,3篇中,我大概介绍了RxJava是怎么使用的。下面我会介绍如何在Android中使用RxJava.RxAndroidRxAndroid是RxJava的一个针对Android平台的扩展。它包含了一些能够简化And......
  • Transform操作——移动旋转缩放
    Transform操作——移动旋转缩放1.移动transform.Translate(Vector3.left*(mouse_x*15f)*Time.deltaTime);cube.transform.position=cube.transform.position+newVector3(0.5f,0f,0f); 2.旋转 cube.transform.Rotate(newVector3(0,10,......