在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中围绕两个手指的中点缩放 的相关文章

  • 如何在 Spring 中使 @PropertyResource 优先于任何其他 application.properties ?

    我正在尝试在类路径之外添加外部配置属性资源 它应该覆盖任何现有的属性 但以下方法不起作用 SpringBootApplication PropertySource d app properties public class MyClass
  • 如何在java中将日期格式从YYMMDD更改为YYYY-MM-DD? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我从机器可读代码中获取日期格式为 YYMMDD 如何将其更改为 YYYY MM DD 例如我收到 871223 YYMMDD 我想把它改成
  • Android应用主题更换流畅

    我正在开发一个提供白天和夜间主题的项目 我正在更改主题 夜间主题 AppCompatDelegate setDefaultNightMode AppCompatDelegate MODE NIGHT YES 日主题 AppCompatDel
  • Akka 与现有 java 项目集成的示例

    如果我已经有现有的javaWeb 应用程序使用spring and servlet容器 将 Akka 集成到其中的正确方法是什么 就像我将会有Actor1 and Actor2互相沟通的 开始使用这些演员的切入点是什么 例如 1 把它放在那
  • Jetpack Compose 中复选框中的透明复选标记

    在我的 Compose 应用程序中 我需要创建一个圆形复选框 我已经通过下面的代码实现了这一点 Composable fun CircleCheckBox isChecked Boolean modifier Modifier Modifi
  • Android:如何创建模态进度“轮”叠加层?

    我想在我的视图上显示模式进度 轮子 叠加层 ProgressDialog 很接近 但我不想要对话框背景或边框 我尝试设置对话框窗口的背景可绘制 this progressDialog new ProgressDialog Main this
  • 蓝牙发送和接收文本数据

    我是 Android 开发新手 我想制作一个使用蓝牙发送和接收文本的应用程序 我得到了有关发送文本的所有内容逻辑工作 但是当我尝试在手机中测试它时 我看不到界面 这是Main Activity Code import android sup
  • 如何区分从 Saxon XPathSelector 返回的属性节点和元素节点

    给定 XML
  • 以编程方式向 LinearLayout 添加边框

    我该如何添加以编程方式LinearLayout 的边框 假设我们创建了这个布局 LinearLayout TitleLayout new LinearLayout getApplicationContext TitleLayout setO
  • 在android中从SD卡上传图像到facebook

    我无法从 SD 卡上传 Facebook 上的图像 我使用了下面的代码 但它没有给我错误 但同时它没有上传图像 byte data null try FileInputStream fis new FileInputStream filep
  • 使用 HtmlUnit 定位弹出窗口

    我正在构建一个登录网站并抓取一些数据的程序 登录表单是一个弹出窗口 所以我需要访问这个www betexplorer com网站 在页面的右上角有一个登录链接 写着 登录 我单击该链接 然后出现登录弹出表单 我能够找到顶部的登录链接 但找不
  • 手动设置Android Studio的JDK路径

    如何为 Android Studio 使用自定义 JDK 路径 我不想弄乱 PATH 因为我没有管理员权限 是否有某个配置设置文件允许我进行设置 如果您查看项目设置 您可以从那里访问 jdk 在标准 Windows 键盘映射上 您可以在项目
  • Android S8+ 警告消息“不支持当前的显示尺寸设置,可能会出现意外行为”

    我在 Samsung S8 Android 7 中收到此警告消息 APP NAME 不支持当前的显示尺寸设置 可能会 行为出乎意料 它意味着什么以及如何删除它 谢谢 通过添加解决supports screens 机器人 xlargeScre
  • android系统用户和linux root用户有什么区别

    当我将手机连接到电脑并使用adb shell与我的手机通信并输入的命令ps命令输出当前在我的手机上运行的进程信息 我发现有两个特殊用户 一个是root 另一个是system 据我所知 Android是基于linux的 所以root用户是最大
  • 如何在android中安装和使用couch db

    我应该如何在 android 中安装和使用 couch Db 我的意思是本地沙发数据库 我可以在平板电脑和模拟器中使用它 为此我必须遵循哪些步骤 我目前正在开发一个使用它的项目 有两种选择 1 couchbase android 是的 co
  • ARM Chromebook 上的 Android 开发环境?

    我尝试了多次安装和使用安卓工作室 https developer android com studio index html on an ARM Chromebook C100P https archlinuxarm org platfor
  • Java/Python 中的快速 IPC/Socket 通信

    我的应用程序中需要两个进程 Java 和 Python 进行通信 我注意到套接字通信占用了 93 的运行时间 为什么通讯这么慢 我应该寻找套接字通信的替代方案还是可以使其更快 更新 我发现了一个简单的修复方法 由于某些未知原因 缓冲输出流似
  • Java RMI - 客户端超时

    我正在使用 Java RMI 构建分布式系统 它必须支持服务器丢失 如果我的客户端使用 RMI 连接到服务器 如果该服务器出现故障 例如电缆问题 我的客户端应该会收到异常 以便它可以连接到其他服务器 但是当服务器出现故障时 我的客户端什么也
  • MiniDFSCluster UnsatisfiedLinkError org.apache.hadoop.io.nativeio.NativeIO$Windows.access0

    做时 new MiniDFSCluster Builder config build 我得到这个异常 java lang UnsatisfiedLinkError org apache hadoop io nativeio NativeIO
  • java'assert'和'if(){}else exit;'之间的区别

    java和java有什么区别assert and if else exit 我可以用吗if else exit代替assert 也许有点谷歌 您应该记住的主要事情是 if else 语句应该用于程序流程控制 而assert 关键字应该仅用于

随机推荐