在android中使用多点触控进行旋转、缩放和移动

2024-04-18

我想在多点触摸事件上旋转、缩放和移动图像,它似乎工作正常,但工作不完美。我真的很想修复我的错误代码,所以请帮助我。我的代码在那里

public class ImageControl extends Activity {
    DragView dragView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dragView = new DragView(this);
        setContentView(dragView);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.image_control, menu);
        return true;
    }
    class DragView extends ImageView
    {
        private Bitmap bitmap;

                private float width;
        private float height;

        private float startX=0;
        private float startY=0;

        private float userX=0;
        private float userY=0;

        private Paint paint;

        private float oldDistance = 1f;
        private float newDistance = 1f;

        private Rect rect;

        static final int NONE = 0;
        static final int DRAG = 1;
        static final int ZOOM = 2;
        int mode = NONE;    

        private int lastAngle=0;

        private int thisAngle=0;

        private int deltaAngle;

        private int angle;

        int rotateX, rotateY;

        private Matrix mat;

        private float x1;
        private float y1;

        public DragView(Context context){
            super(context);
            init();
            setImage(context);
        }
        private void init(){
            paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStyle(Paint.Style.STROKE);
            paint.setAntiAlias(true);
            mat = new Matrix();
        }
        private void setImage(Context context){
            bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.android);
            width = bitmap.getWidth();
            height = bitmap.getHeight();
        }
        public void onDraw(Canvas canvas){
            if(bitmap!=null)
            {
                canvas.drawBitmap(bitmap, mat, null);
                canvas.drawRect(userX, userY, userX+width, userY+height, paint);
            }
        }
        public Rect getRect(){
            rect = new Rect();
            rect.set((int)userX, (int)userY, (int)(userX+width), (int)(userY+height));
            return rect;
        }
        public void setXY(float x, float y){
            startX = x;
            startY= y;

        }
        public boolean onTouchEvent(MotionEvent event){
            x1 = event.getX(0);
            y1 = event.getY(0);
            int act = event.getAction();
            switch(act&MotionEvent.ACTION_MASK){
            case MotionEvent.ACTION_DOWN:
                setXY(x1, y1);
                mode=DRAG;
                break;
            case MotionEvent.ACTION_MOVE:
                if(mode==ZOOM){
                    newDistance = spacing(event);
                    float scale2 = FloatMath.sqrt(((newDistance-oldDistance)*(newDistance-oldDistance))
                            /(height*height+width*width));
                    float scale = newDistance / oldDistance;
                    if(newDistance - oldDistance > 0){
                        setZoom(scale, scale2);
                    }else if(oldDistance - newDistance > 0){
                        setZoom(scale, -scale2);
                    }
                    setRotate(event, x1, y1);
                }
                else if(mode==DRAG){
                    setLastXY(x1-startX, y1-startY);
                    setXY(x1, y1);
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                    mode = ZOOM;
                    float value = spacing(event);
                    oldDistance = value;
                    newDistance = value;
                    break;
            case MotionEvent.ACTION_CANCEL:
            default:
                    break;
            }
            return true;
        }
        private void setLastXY(float x, float y){
            userX += x;
            userY += y;
            mat.setTranslate(userX, userY);
            invalidate();
        }
        private float spacing(MotionEvent event){
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return FloatMath.sqrt(x*x+y*y);
        }
        private void setZoom(float scale, float scale2){

            userY=userY-(height*scale2/2);
            userX=userX-(width*scale2/2); 
            height=height*(1+scale2);
            width=width*(1+scale2);
            Log.d("ZoomTAG", "scale:"+scale);
            mat.postScale(scale, scale, userX+width/2, userY+height/2);
            oldDistance = newDistance;
            invalidate();
        }
        private void setRotate(MotionEvent event, float x1, float y1){
            float x2 = event.getX(1);
            float y2 = event.getY(1);
            thisAngle = (int)Math.toDegrees(Math.atan2(-(y2-y1), x2-x1));
            if(lastAngle==0){
                lastAngle=thisAngle;
            }
            deltaAngle = thisAngle-lastAngle;
            angle += -deltaAngle;
            lastAngle = thisAngle;
            float minX = Math.min(x1, x2);
            float minY = Math.min(y1, y2);
            rotateX = (int)minX + (Math.abs((int)(x1-x2))/2);
            rotateY = (int)minY + (Math.abs((int)(y1-y2))/2);
            Log.d("TAG", "Angle : " + angle);
            mat.postRotate(angle, userX+width/2, userY+height/2);
            invalidate();
        }
    }
}

最好的方法是使用矩阵进行更改(调整大小、旋转),而不会造成任何质量损失。尝试这样的事情 http://judepereira.com/blog/multi-touch-in-android-translate-scale-and-rotate/仔细观察ACTION_DOWN和ACTION_MOVE:

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class MultiTouch extends Activity implements OnTouchListener {

// these matrices will be used to move and zoom image
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
// we can be in one of these 3 states
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
// remember some things for zooming
private PointF start = new PointF();
private PointF mid = new PointF();
private float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
private float[] lastEvent = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ImageView view = (ImageView) findViewById(R.id.imageView);
    view.setOnTouchListener(this);
}

public boolean onTouch(View v, MotionEvent event) {
    // handle touch events here
    ImageView view = (ImageView) v;
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            mode = DRAG;
            lastEvent = null;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if (oldDist > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
            }
            lastEvent = new float[4];
            lastEvent[0] = event.getX(0);
            lastEvent[1] = event.getX(1);
            lastEvent[2] = event.getY(0);
            lastEvent[3] = event.getY(1);
            d = rotation(event);
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            lastEvent = null;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                matrix.set(savedMatrix);
                float dx = event.getX() - start.x;
                float dy = event.getY() - start.y;
                matrix.postTranslate(dx, dy);
            } else if (mode == ZOOM) {
                float newDist = spacing(event);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float scale = (newDist / oldDist);
                    matrix.postScale(scale, scale, mid.x, mid.y);
                }
                if (lastEvent != null && event.getPointerCount() == 3) {
                    newRot = rotation(event);
                    float r = newRot - d;
                    float[] values = new float[9];
                    matrix.getValues(values);
                    float tx = values[2];
                    float ty = values[5];
                    float sx = values[0];
                    float xc = (view.getWidth() / 2) * sx;
                    float yc = (view.getHeight() / 2) * sx;
                    matrix.postRotate(r, tx + xc, ty + yc);
                }
            }
            break;
    }

    view.setImageMatrix(matrix);
    return true;
}

/**
 * Determine the space between the first two fingers
 */
private float spacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return FloatMath.sqrt(x * x + y * y);
}

/**
 * Calculate the mid point of the first two fingers
 */
private void midPoint(PointF point, MotionEvent event) {
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
}

/**
 * Calculate the degree to be rotated by.
 *
 * @param event
 * @return Degrees
 */
private float rotation(MotionEvent event) {
    double delta_x = (event.getX(0) - event.getX(1));
    double delta_y = (event.getY(0) - event.getY(1));
    double radians = Math.atan2(delta_y, delta_x);
    return (float) Math.toDegrees(radians);
}

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在android中使用多点触控进行旋转、缩放和移动 的相关文章

随机推荐

  • Windows 窗体中的本机外观(类似资源管理器)主菜单

    除了使用 MenuStrip 之外 还有其他方法在 C 中创建主菜单吗 它看起来与标准资源管理器菜单不相似 我在这里做错了什么吗 我只想要标准应用程序主菜单 例如浏览器菜单 听起来您想要一个尊重操作系统主题的菜单 MainMenu 类将执行
  • 使用 Android 应用程序访问 SIM 卡?

    我想知道是否可以使用 Android 应用程序访问 SIM 卡 你可以像这样获取 IMEI 但这是你想要的吗 只是一个例子 mTelephonyMgr TelephonyManager getSystemService Context TE
  • API 平台 - 我应该使用哪种方法来创建没有实体的自定义操作

    我是 API 平台的新手 我认为这很棒 但我找不到任何示例如何创建不基于任何实体的自定义端点 有很多基于实体的示例 通常都是关于 CRUD 的 但是自定义操作呢 我需要使用一些与任何实体无关的自定义参数通过数据库创建自定义搜索 例如 我想接
  • ASP中,位运算符左移和右移

    有谁知道左移和右移运算符示例吗 我是 ASP 新手 我发现了位运算符 例如 AND OR NOT 等等 对于 vbscript 左移是通过乘法完成的 即 var 2 左移一个位置 var 4 左移两个位置等 右移是通过除法完成 即 var
  • Zend Framework 2 的多个表

    我是 Zend Framework 2 的新手 我成功完成了 ZF2 的专辑教程 现在我想仅显示数据库中多个表中的某些数据 我有一个简单的数据库设置 其中包含表格 例如人员 书籍 状态等 数据库应该做什么并不重要 我想知道是否有一个教程可以
  • 从 C 代码获取当前使用的文件描述符的计数

    是否有 C API 可以获取 系统范围内当前使用的文件描述符 当前进程当前使用的文件描述符 对于当前进程计数 您可以使用getrlimit获取文件描述符限制 然后迭代从 0 到该限制的所有整数并尝试调用fcntl与F GETFD命令 它只会
  • PubNub:将所有已发布消息记录到我的数据库的正确方法是什么

    记录每条已发布消息并将其保存到我的服务器数据库的正确方法是什么 我能想到的有两种选择 使用PubNub功能发布事件后并将消息转发到专用记录器通道 服务器将订阅该频道并将到达的消息保存到数据库 这里又产生一个问题 当我在PubNub函数中将消
  • 使用 ActiveRecord 和 Rails 3 进行复杂 JOIN

    我有以下型号 class User lt ActiveRecord Base has many memberships has many groups through gt memberships end class Group lt Ac
  • 如何在 C# 中旋转标签? [复制]

    这个问题在这里已经有答案了 我想显示一个旋转 90 度的标签 这样我就可以将它们中的一堆作为标题放在表格的顶部 是否有捷径可寻 您需要编写自己的控件或使用自定义控件 A 代码项目 http en wikipedia org wiki The
  • Qt 和 Google 地球 API

    是否可以使用 Google Earth 在 Qt 中开发应用程序 例如 我想在我的应用程序中通过 QtGL 将地球 如谷歌地球 显示为球体 很明显 您可以在 Qt 中使用 google Earth api 我想分享一个秘密 Google E
  • AABB 碰撞解决滑动边

    因此 我目前正在重新发明轮子 并学到很多东西 尝试为我的游戏引擎制作一个简单的物理引擎 我一直在互联网上搜索 尝试 但失败 解决我当前的问题 关于这个主题有很多资源 但我发现的资源似乎都不适用于我的情况 问题简而言之 当两个矩形碰撞时 碰撞
  • 如何对选择器输入中的选项进行文本换行,如果选项的长度很长,则选项通常会出现在屏幕之外

    pickerInput 中的选择始终位于单行中 有没有办法可以将它们带到下一行 当选择的长度很长导致选择超出屏幕时 这是一个问题 我特别需要 pickerInput 因为它具有实时搜索 全选 取消全选功能 library shiny lib
  • gcc -lpthread 不工作

    我的系统中安装了 ubuntu 11 我有一个使用 pthread 库的 C 程序 我收到错误Undefined reference to sem wait 即使我已经用标志编译了 lpthread 例如 gcc lpthread prog
  • 如何在 drools 规则引擎中动态更新规则

    我正在开发 drools 规则引擎 在这个场景中将 when 块中的值从 1000 更改为 2000 将符号从 gt 更改为 rule payment when account Paymentinfo transaction lt 1000
  • 使用python将数据写入谷歌云存储

    我找不到使用 python 将本地计算机中的数据集写入谷歌云存储的方法 我进行了很多研究 但没有找到任何与此相关的线索 需要帮助 谢谢 简单的例子 使用谷歌云 https googlecloudplatform github io goog
  • 使用 GTK 构建 GUI#

    我可能需要使用 C 和 Mono 构建 GTK GUI 如果我理解正确的话 这意味着我有3个选择 编写 C 代码来调用 GTK 包装器类 GUI 是 在代码中 使用 MonoDevelop GUI 设计器 这使用 stetic 标记构建了一
  • 在 Xamarin.Forms 中编写设备平台特定的代码

    我有以下内容Xamarin Forms ContentPage类结构 public class MyPage ContentPage public MyPage do work to initialize MyPage public voi
  • 在 Apps 脚本上创建新触发器时收到错误

    尝试创建新触发器时收到此错误 脚本授权失败 请检查您的弹出窗口阻止程序设置 然后重试 已尝试允许该网站接受弹出窗口 甚至关闭弹出窗口阻止程序 但没有产生任何影响 有人有解决办法吗 我遇到了同样的问题 并设法通过首先从脚本编辑器手动执行我的脚
  • PHP 7 用户会话问题 - 无法初始化存储模块

    在 PHP 7 0 中使用各种 PHP 框架会话驱动程序时存在错误 我最初在使用 CodeIgniter 数据库驱动程序时遇到了这个问题 并认为这是一个 CodeIgniter 问题 但后来在多个会话驱动程序和多个框架上遇到了这个问题 此时
  • 在android中使用多点触控进行旋转、缩放和移动

    我想在多点触摸事件上旋转 缩放和移动图像 它似乎工作正常 但工作不完美 我真的很想修复我的错误代码 所以请帮助我 我的代码在那里 public class ImageControl extends Activity DragView dra