在android中围绕两个手指的中点缩放

2024-04-13

我有一个HorizontalScrollView其中有多个视图。我已经实施了pinch zoom gesture其中我的两根手指之间的多个视图被缩放。

但我面临一个小问题。当我进行捏缩放时,捏缩放的中点正在移动,但为了用户体验,我希望该点保持固定,其他内容应在缩放时自行调整,以便中点保持静态。

有人可以告诉我该怎么做吗?

onDraw()自定义视图的方法是

                Rect r =new Rect(0, 0, 700, 40);

    public void onDraw(Canvas canvas) {

        float kk=mScaleFactor;    //this variable will be set by pinch zoom event and represent how much to scale
        sf*=kk;                   // this view must scale according to previous scaling  


        canvas.save();
        canvas.scale(sf , 1);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.BLUE); 
        canvas.drawRect(r, paint);
        width=sf*700;
        canvas.restore();
        requestLayout();                               //this will change view width to fit the expanded rectangle 
        }

onMeasure 方法在 requestLayout 上调用

        @Override protected void onMeasure(int widthMeasureSpec,
              int heightMeasureSpec) {
            setMeasuredDimension((int)width, 340);
          }

上面的自定义视图被 的子类调用了 12 次HorizontalScrollView。所以有 12 个子视图HorizontalScrollview.

在这堂课上我正在做以下事情

  1. 检测两个手指的触摸坐标。

  2. 计算第一个手指触摸的子视图的索引。

  3. 计算第二根手指触摸的子视图的索引。

  4. 将捏缩放的比例因子传递给开始和最后之间的所有子视图。 这两个指标是在前两步中计算出来的。

  5. 最后在子视图上调用 invalidate() 。因此子视图可以根据父视图传递的比例因子来缩放自身。

但这里有一个问题。两个手指的中点应保持静止,其他部分应在缩放过程中进行调整。但我的中心点是随着规模的扩大而变化。

有人可以帮我做这件事吗?请告诉我是否需要代码的任何部分。

手势监听代码HorizontalScrollview is

      private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
               mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

            ViewGroup pp=takeparent(); //give object of this class

            for(int i=start;i<=last;i++)
            {
                LinearLayout ll=(LinearLayout)pp.getChildAt(i);
                DrawView view=(DrawView)ll.findViewById(R.id.drawview);
                view.mScaleFactor=mScaleFactor;
                view.invalidate();
                view.donesf=true;
            }

Sample app of mine enter image description here

按照评论中的建议进行编辑:

        private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
               mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

            ViewGroup pp=takeparent(); pp contains all the custom child views

            //start and last are indices of range of child for which we have to apply gesture
            for(int i=start;i<=last;i++)
            {
                LinearLayout ll=(LinearLayout)pp.getChildAt(i);
                DrawView view=(DrawView)ll.findViewById(R.id.drawview);

                view.mScaleFactor=mScaleFactor;
                view.pivotx=detector.getFocusX()+view.getLeft();
                view.pivoty=detector.getFocusY()+view.getTop();
                view.invalidate();
            }




            return true;
        } 

这是自定义视图的onDraw方法

       public void onDraw(Canvas canvas) {

        sf=mScaleFactor  //this scale factor is set by parent view    
        width=sf*700;  //this width will be use to rescale the view's width in requestLayout()

        canvas.save();

        canvas.scale(sf,1,pivotx,pivoty);  //pivotX and pivotY are also set by parent's onScale method of gestureListener
        canvas.drawRect(r, paint);
        requestLayout();
        canvas.restore();

        } 

对于要缩放的视图,您可以使用以下命令设置不应移动的“不变”点setPivotX() and setPivotY()。当我使用ScaleGestureDetector, 我用focus这点。例如:

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector)
    {
        ...
        mScaledView.setPivotX(detector.getFocusX());
        mScaledView.setPivotY(detector.getFocusY());
        ...

我不确定您是否想对所有子视图执行此操作,或者仅对父视图执行此操作,在您的情况下,但通常您只需要对单个“父”视图执行此操作,它将对子视图正常工作的观点。

与此相关的是,我不太明白为什么在缩放父视图也会缩放其所有子视图时将缩放因子传递给每个子视图。也许你只需要添加一个FrameLayout(或其他一些ViewGroup后代)进入你的HorizontalScrollView托管孩子,然后缩放它(在适当设置其枢轴后)?


更新了评论

鉴于您只想缩放手指之间捏合区域的视图,我相信您有几个选择,具体取决于您的应用程序:

1)动态地将这些视图添加到中间FrameLayout它被缩放并设置了枢轴,将非缩放视图保留为直接子视图HorizontalScrollView; or

2) 在第一次调整子视图的位置后,将焦点向下传递到每个缩放的子视图。例如,假设您的DrawView直接或间接继承自android.view.View,我强烈推荐,那么你可以这样做:

    for (int i = start; i <= last; i++) {
        LinearLayout ll = (LinearLayout)pp.getChildAt(i);
        DrawView view = (DrawView)ll.findViewById(R.id.drawview);

        view.setScaleX(mScaleFactor);
        view.setScaleY(mScaleFactor);
        view.setPivotX(detector.getFocusX() - view.getLeft());    // Note: minus, not plus...
        view.setPivotY(detector.getFocusY() - view.getTop());
        view.invalidate();
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在android中围绕两个手指的中点缩放 的相关文章

  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • Android 手机作为 GSM 调制解调器在 PC 上发送/接收短信?

    是否可以将 Android 移动设备用作 PC 上的 GSM 调制解调器 我正在 net下开发应用程序来发送 接收短信等 现在我想通过 USB 将我的 Android 设备连接到我的 PC 并将其用作 GSM 调制解调器来与其通信 这里是参
  • 如何对不同的参数类型使用相同的java方法?

    我的问题 我有 2 个已定义的记录 创建对象请求 更新对象请求 必须通过实用方法进行验证 由于这两个对象具有相同的字段 因此可以对这两种类型应用相同的验证方法 现在我只是使用两种方法进行重载 但它很冗长 public record Crea
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • Android - AudioRecord类不读取数据,audioData和fftArray返回零

    我是 Android 新手 一直在开发音调分析器应用程序 最低 SDK 8 我读了很多关于如何实现 Audiorecord 类的文章 但我想知道为什么它在我录制时不读取任何数据 我尝试显示 audioData 和 fftArray 的值 但
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • okhttp 获取失败响应

    我已经在我的 android 客户端中实现了 okhttp 来进行网络调用 当我收到失败响应时 我会收到失败代码以及与该代码相关的文本作为消息 但我没有收到服务器发送给我的自定义失败响应 在我实施的代码中的失败响应中 我收到的消息只是 错误
  • 为什么 Java 8 不允许非公共默认方法?

    让我们举个例子 public interface Testerface default public String example return Hello public class Tester implements Testerface
  • Eclipse 选项卡宽度不变

    我浏览了一些与此相关的帖子 但它们似乎并不能帮助我解决我的问题 我有一个项目 其中 java 文件以 2 个空格的宽度缩进 我想将所有内容更改为 4 空格宽度 我尝试了 正确的缩进 选项 但当我将几行修改为 4 空格缩进时 它只是将所有内容
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • Android 如何将总天数准确更改为年、月、日?

    我正在做一个应用程序 该应用程序与根据给定的生日日期输入获取一个人的年龄有关 为此 我从下面的代码中获取从该日期到当前日期的总天数 String strThatDay 1991 05 10 SimpleDateFormat formatte
  • Android 中的处理程序与异步调用

    目前我正在使用处理程序来调用 Web 服务方法以使其在后台运行 问题是它需要更多的时间来给出响应 在性能方面似乎更昂贵 现在我计划使用异步调用 哪一个是最好的 Android 中的处理程序和异步调用有什么区别 请帮我想出一个最好的解决方案
  • 在 Samsung Galaxy S5 Android 5.0 上使用 MediaPlayer 加载音频流需要超过 10 秒

    由于更新至 Android 5 0 MediaPlayer 在 Samsung Galaxy S5 上无法正常工作 启动音频流后加载时间超过 10 秒 示例代码 MediaPlayer mPlayer new MediaPlayer Str
  • 没有用于警告的设置器/字段 Firebase 数据库检索数据填充列表视图

    我只是想将 Firebase 数据库中的数据填充到我的列表视图中 日志显示正在检索数据 但适配器不会将值设置为列表中单个列表项中的文本 它只说 没有二传手 场地插入值 这让我觉得我的设置器没有正确制作 但 Android Studio 自动
  • 通过系统应用程序以编程方式静默安装 apk(无需 root)

    我有带有 android sharedUserId android uid system UID 1000 的系统级应用程序 设备未root INSTALL PACKAGES 权限包含在清单中 我可以静默安装下载的 apk 吗 我已经发现这
  • 插件“Android Bundle Support”不兼容

    大家好 自从上次更新以来 当我启动 android studio 时 我遇到了一个非常奇怪的错误 我有这个错误 插件错误 插件 Android Bundle Support 不兼容 直到构建 AI 195 SNAPSHOT 我在网上找不到任
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 发布的 Android apk 出现错误“包文件未正确签名”

    我最近将我的应用程序上传到 Android 市场 但是由于错误 下载时它拒绝运行 包文件未正确签名 我首先使用 eclipse 发布了数据包 右键单击导出 创建密钥库然后发布 但它拒绝工作 然后我下载了 keytool 和 jarsigne

随机推荐