上一篇介绍安卓Gesture手势初步使用,这一篇用Gesture来实现多点触控达到控制图片放大缩小。

上文中写道,进行手势监听的Activity要实现对应的OnGestureListener接口,重写其中的几个方法,其中最关键的两个方法:

@Override/* 手指滑动触发 */public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {return false;}@Override/* 手指抛掷(快速划屏幕后松开) */public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {return false;}

这两个方法都传入了四个参数,分别代表:

e1: 第一个按下时的事件,可以当做第一次按下时的点

e2: 移动时的事件,分别用于触发scroll和fling

在onScroll中;

dsitanceX表示每次滑动的X方向的偏移量
dsitanceY表示每次滑动的Y方向的偏移量

在onFling中:

velocityX表示X方向的速度
velocityY表示Y方向的速度

知道了这个以后,我们要实现多点触控,那么怎么获取触摸时的多个点呢,这里有一个坑,大部分人认为是通过onScroll的e1.getPointCount( ),测试以后会发现,触摸点永远是1,其实e1代表的是第一个触摸到屏幕的那个手指的事件,即使你看上去两个手指是同时按下的,也有一个手指是最先碰到屏幕的,而这个手指就产生了这个MotionEvent e1,所以触摸点数永远是1。

真正的做法是,在onScroll()中使用

e2.getPointCount( )

来获取触摸点的数量,一般来说控制图片的放大缩小两个点就够了,这里以两个触摸点为例。

获取到触摸点以后,接下来就通过获取到的触摸点来判断监听事件,对图片进行相关操作.一般我们使用相册什么的对图片进行放大缩小是用两根手指,根据两点的距离变化来判断是要放大还是要缩小图片,其中对于的手指滑动的手势,会回调我们的onScroll和onFling,其中onScroll会随着手指滑动一直调用,就类似onTouch里监听到MotionEvent为Action_Move一样。所以我们重点重写这两个方法,并通过一个全局变量来保存每次滑动的距离,方便比较大小。

先贴代码,然后总结下里面容易踩到的坑。

代码:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.chan.gesturepointstouch.MainActivity"><ImageView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/iv"android:layout_centerInParent="true"android:src="@mipmap/ic_launcher"/>
</RelativeLayout>

MainActivity:

package com.chan.gesturepointstouch;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;/*** 多点触控 ,控制图片缩放*/
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener {private GestureDetector detector;private ImageView iv;private float lastDistance = -1f;// 记录上一次两点的距离@Overrideprotected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState);setContentView (R.layout.activity_main);detector = new GestureDetector (this, this);iv = (ImageView) findViewById (R.id.iv);}@Overridepublic boolean onTouchEvent (MotionEvent event) {return detector.onTouchEvent (event);}@Overridepublic boolean onDown (MotionEvent e) {// 每次按下后重新复位-1flastDistance = -1f;return false;}@Overridepublic void onShowPress (MotionEvent e) {}@Overridepublic boolean onSingleTapUp (MotionEvent e) {return false;}@Overridepublic boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {// 从e2获取触点数量int pointCount = e2.getPointerCount ();if (pointCount == 2) {float deltaX = e2.getX (1) - e2.getX (0);float deltaY = e2.getY (1) - e2.getY (0);float distance = (float) Math.sqrt (deltaX * deltaX + deltaY * deltaY);// 误差值float slop = 5;RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) iv.getLayoutParams ();if (lastDistance < 0) {lastDistance = distance;} else {// 真正的比较if (distance - lastDistance > slop) {// 放大,最大放大到500Log.d ("tag", "放大");if (layoutParams.width < 800) {layoutParams.width = (int) (iv.getWidth () * 1.1f);layoutParams.height = (int) (iv.getHeight () * 1.1f);iv.setLayoutParams (layoutParams);} else {Toast.makeText (MainActivity.this, "不能再放大了", Toast.LENGTH_SHORT).show ();}} else if (distance - lastDistance < slop) {// 缩小,最小缩小到100Log.d ("tag", "缩小");if (layoutParams.width > 50) {layoutParams.width = (int) (iv.getWidth () * 0.9f);layoutParams.height = (int) (iv.getHeight () * 0.9f);iv.setLayoutParams (layoutParams);} else {Toast.makeText (MainActivity.this, "不能再缩小了", Toast.LENGTH_SHORT).show ();}}}}return false;}@Overridepublic void onLongPress (MotionEvent e) {}@Overridepublic boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return false;}
}

其中重点:

  • 每次回调onScroll都计算出两触摸点的距离(利用勾股定理),判断下如果lastDistance=-1,即没有保存状态,就保存当前的状态,继续滑动就继续回调onScroll,此时lastDistance保存的是上一次的两触摸点的距离,执行比较距离的代码~

  • 比较的时候给了一个临界值slop,这个值用于避免手指很微小的误操作都被捕捉到,并且这个值也不能太大,否则手指很难滑到这个临界值。

  • 比较时添加了判断图片大小,如果图片大到一定值就不允许继续放大,如果小到一定值就不允许继续缩小。

-改变图片大小用LayoutParams布局参数,每次判断完是放大还是缩小后按一定比例设置LayoutParams的宽高,再重新赋值给图片ImageView

  • 每次执行完一个完整的流程后要将全局的lastDistance复位为-1f,否则会保存上一次的触摸点的距离。

下一篇:安卓Gesture手势(3)-实现自定义手势。(待续)

Iwfu-安卓Gesture手势(2)-实现多点触控控制图片的放大缩小。相关推荐

  1. Android官方开发文档Training系列课程中文版:手势处理之多点触控处理

    原文地址:http://android.xsoftlab.net/training/gestures/multi.html 多点触控是指多个手指同时触摸屏幕的情况.这节课主要学习如何检测多点触控手势. ...

  2. android 多点触控缩放,Android多点触控(图片的缩放Demo)

    本文主要介绍Android的多点触控,使用了一个图片缩放的实例,来更好的说明其原理.需要实现OnTouchListener接口,重写其中的onTouch方法. 实现效果图: 源代码: 布局文件: ac ...

  3. Android自定义控件ImageViwe(四)——多点触控实现图片的自由移动

    效果图: 功能 : 可以随手指进行自由移动图片 按照适当的比例设置图片的显示 首先将图片按照适当的比例显示在自定义控件中(当图片的宽度或者高度大于控件的宽度或者高度的时候,会对图片进行适当的缩放,当图 ...

  4. android多点触控,图片的拖拽与放大缩小

    //直接复制粘贴就可以使用 public class MainActivity extends AppCompatActivity {private ImageView MyImageView;pri ...

  5. Android 多点触控与图片缩放

    上一章,我们学习了手势 GestureDecetor 的基本使用 Android 手势学习 GestureDetector,这一次,我们来学习使用 ScaleGestureDetector 来实现一个 ...

  6. Android 多点触控(放大、缩小、旋转、位移)

    通过多点触控实现图片的放大.缩小.旋转.位移效果. private float oldX1 = 0;private float oldX2 = 0;private float oldY1 = 0;pr ...

  7. windows8 开发教程 教你制作 多点触控Helper可将任意容器内任意对象进行多点缩放...

    实现方法: 对Manipulation进行抽象化 使不同容器可共用多点缩放事件, C# 代码如下: using System; using System.Collections.Generic; us ...

  8. 10_10_安卓加linux命令,Scrcpy 1.11版支持Android 10及多点触控手势,附Linux下安装命令...

    Scrcpy 1.11版本增加了对Android 10的支持及多点触控手势,现在就可以在Linux系统下安装Scrcpy的更新版本,该工具可让你在PC上镜像Android手机. 更新说明 Scrcpy ...

  9. windows7中的多点触控中的手势

    每当用户触摸触敏式 Windows 7 设备时,Windows 7 多点触控平台都会向您的应用程序发送手势消息 WM_GESTURE.这是现成的免费行为,如果您希望停止接收此类消息,则需要选择退出. ...

最新文章

  1. linux哪个版本支持多线程,关于Linux操作系统的叙述错误的是()A、Linux是多用户、多任务、支持多线程的操作系统B、Linux的源...
  2. Linux常用命令及技巧4
  3. 这些 Python 不为人知的「坑」,躲都躲不开
  4. visio 画图工具
  5. 通用权限管理系统组件 中集成多个子系统的单点登录(网站入口方式)附源码
  6. Spark源码阅读03-Spark存储原理之存储分析
  7. 离线轻量级大数据平台Spark之MLib机器学习库TF-IDF实例
  8. 转载:Systemd 命令
  9. 数据结构--队列(数组)的一种实现
  10. PHP随机配菜_PHP+JS三级菜单联动菜单实现方法
  11. VTK:IO之ConvertFile
  12. step5 . day4 网络编程 基于UDP协议的网络编程流程及API
  13. word 论文排版 —— 按指定格式章节的自动编号
  14. 求周期字符串的最小子串
  15. My Brute(HDU-3315)
  16. 接口测试--获取动态参数进阶
  17. python的scrapy爬虫模块间进行传参_Python爬虫Scrapy框架之请求传参合日志等级
  18. 汇编语言程序设计(一)
  19. LaTex论文排版 | (23) LaTex中的正上、正下标记以及各种箭头符号总结
  20. linux 防火墙的配置

热门文章

  1. 深入理解Spanner事务
  2. 用mips衡量计算机性能指标是什么,用MIPS衡量的计算机性能指标是什么_常见问题解析...
  3. AntDB数据库携超融合流式实时数仓亮相第25届中国高速公路信息技术化大会
  4. Workbench网格划分(2)
  5. Java 虚拟机执行子系统
  6. 【Python】教你如何一步批量加水印
  7. android 按home键返回到桌面后,再按桌面应用图标又重新打开该应用的解决方法
  8. QObject: Cannot create children for a parent that is in a different thread
  9. IOI1998 Starry Night
  10. JS实现简易版备忘录