Delphi开发APP时的手势处理(缩放、旋转、平移、长按等)

在使用手机时,少不了使用手势了,像滑动,缩放,长按等,

那么如何在Delphi开发的APP中使用手势呢?

Delphi自带有示例,在下面这个目录中,

 可以看到ImageRotation图片旋转,ImageZoom图片缩放,TapAndHold长按这三个示例

我们打开图片缩放的示例ImageZoom来学习一下如何使用手势

这个示例的窗口中间放了一个Image控件

要缩放,就得让窗体响应缩放的事件,

这个设置不在Image控件上,而是在窗体Touch属性中,

展开窗体的Touch属性,

可以看到Delphi的窗体直接支持如下手势:

Zoom:缩放

Pan:平移

Rotate:旋转

TwoFingerTap:两指点按

PressAndTap:按下并点击

LongTap:长按

DoubleTap:连接点两下

如果你想让窗体响应哪些手势,勾上就行,

这个示例窗体勾上了Zoom手势,

表示它只需要处理缩放手势

那么在哪个事件里进行处理呢?

窗体有个OnGesture事件:

事件的定义:

TGestureEvent = procedure(Sender: TObject; const EventInfo: TGestureEventInfo;

var Handled: Boolean) of object;

参数EventInfo里面包含手势的相关信息,

TGestureEventInfo = record

//手势ID,代表什么手势

GestureID: TGestureID;

//触摸的位置

Location: TPointF;

//手势的状态

Flags: TInteractiveGestureFlags;

//旋转的角度

Angle: Double;

//惯性的矢量,在手势操作的时候,

//比如平移手势Pan,需要根据这个矢量来计算页面能在水平和垂直方向惯性滚动多长的距离

InertiaVector: TPointF;

//缩放的距离

Distance: Integer;

//点按的位置

TapLocation: TPointF;

end;

TGestureID这个类型定义在System.UITypes单元,

表示手势的类型,很奇怪为什么没有用枚举类型:

const

// Interactive gesture id’s (maps to Windows 7’s WM_GESTURE)

igiBegin = 1 + igiFirst;

igiEnd = 2 + igiFirst;

igiZoom = 3 + igiFirst;

igiPan = 4 + igiFirst;

igiRotate = 5 + igiFirst;

igiTwoFingerTap = 6 + igiFirst;

igiPressAndTap = 7 + igiFirst;

// Extra interactive gestures

igiLongTap = 8 + igiFirst;

igiDoubleTap = 9 + igiFirst;

TInteractiveGestureFlags 则定义在FMX.Types单元,

标志手势的状态,是手势开始、进行中还是结束了:

TInteractiveGestureFlag = (gfBegin, gfInertia, gfEnd);

TInteractiveGestureFlags = set of TInteractiveGestureFlag;

看下官方的示例中实现图片缩放的代码:

运行看下效果:

jdfw

官方示例只是简单的对图片进行居中缩放,

但是我们在实际使用中,我们通常都是需要对任意一点进行缩放,

比如下面这张图片,

53o9s00511fce4a269f374e4a973fa5f1f9bb5462

我想对她头上的花进行放大,看看到底是什么花,

我将两指对准那朵花进行放大,但是花的位置却上移,

我用官方示例查看的效果:

34.给你的APP加上手势处理-图片缩放 2 jdfw

并且图片控件放大了之后,超出了屏幕的显示区域,超出的区域不能移动,都看不到了。

Screenshot_2022-09-25-15-45-44-114_com.embarcader

那么我们来试着完善下这个示例,

需要完善以下两点:

  1. 图片超出了屏幕显示区域,要能滑动查看被挡住的部分。
  2. 缩放的时候以两根手指的中心点为基点,这个点上不能偏移,比如我想放大美女头上那朵花,将手指放在花的两边进行缩放,缩放的时候,这朵花得一直在屏幕原来的位置上放大,我想要的效果如下,这是我用QQ查看这张图片时缩放的效果:

34.给你的APP加上手势处理-图片缩放 希望达到的效果

先来解决第一个问题,

很简单,将图片控件放到一个ScrollBox里面就行了

放大之后可以滑动了

再来解决第二个问题

先要知道我们两指缩放时的那两个点,

窗体有一个OnTouch事件,

TTouchEvent = procedure(Sender: TObject; const Touches: TTouches; const Action: TTouchAction) of object;

它是一个多点触摸事件,通过它我们能知道当前有几个手指摸在窗体上,

事件中的Touches参数是一个点的数组,会返回当前的触摸点,

如果Touches的长度为2,就表示有两根手指触摸在屏幕上,

在缩放的时候这两个点就是两根手指所触摸的位置,

我们定义两个全局变量,将这两个点保存起来,

var

gFormTouch1:TPointF;

gFormTouch2:TPointF;

我们在对图片控件中心点进行缩放的时候,

比如放大20个像素,

如果仅给图片控件的宽度和高度都加上20,那么中心点就会偏移了,

如下图所示:

那么怎么保持中心点不变呢?

只需要左边和右边各延伸一半,即图片.Left要减10,右边的Right要加10,

如下图:

如果缩放点不是控件的中心点,而是图片控件的1/3处,

那么只需要图片.Left减去20个像素的1/3,图片控件的Right向右再延伸20个像素的2/3,

那么缩放中心点也不会偏移,

如下图所示:

所以缩放时中心点不偏移的公式:

控件位置=控件位置-缩放尺寸*缩放中心点位置的比例

比如控件位置Left为10,缩放了20个像素,缩放中心点在图片控件的1/3处,

那么首先控件宽度要加上20,

然后控件的Left要减去20*1/3(约7),就变成了3

在手势缩放开始的时候,通过触摸的两个点,计算出缩放中心点,

这两点目前是基于窗体的坐标,要先转换成相对于图片控件的坐标,

所以还需要一些变量:

//图片控件上的两个触摸点

gImageControlTouch1:TPointF;

gImageControlTouch2:TPointF;

//图片控件上的两个触摸点的中心点

gImageControlTouchCenter:TPointF;

//中心点占图片宽度的百分比

gImageControlTouchCenterWidthRate:Double;

//中心点占图片高度的百分比

gImageControlTouchCenterHeightRate:Double;

先做开始缩放的准备,

代码如下:

在缩放的时候,保持缩放中心点的物体不偏移:

代码如下:

因为每次生成到Android手机再调试有点慢,

所以我先在Windows平台测试,

放一个按钮,直接调用FormGesture事件来模拟手势缩放,

先找到花相对于图片控件的坐标,是(120,45)

先模拟缩放开始,让它计算出中心点:

并且为了直观的展示缩放中心点的物体不产生偏移,我将它这个点的位置画出来:

再放个按钮,点击它,模拟缩放的过程:

先在Windows下运行试试:

先点“模拟缩放开始”按钮,可以看到缩放中心在那朵花上,

点击“模拟缩放进行”按钮:

可以看到,图片放大了之后,这红点的位置没有发生偏移,

并且红点所在的还是在这朵花的位置,

34.给你的APP加上手势处理-图片缩放 3 jdfw

然后在手机上模拟一下:

34.给你的APP加上手势处理-图片缩放 4 jdfw

手势的处理大致就是这么一个流程了,

大家有兴趣可以自己体验一下。

http://qiniuoss.orangeui.cn/ImageZoomAtFingerCenter.apk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/637855.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI Summary

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Spring AI is a project that aims to streamline the development of AI applications by providing abstractions and reusable components that can be easily integrate…

CSS——前端笔记

CSS 1、选择器1.1、基础选择器1.2、复合选择器1.2.4、伪类选择器 1.3、属性选择器1.4、结构伪类选择器1.5、伪元素选择器 2、CSS的元素显示模式2.1、块元素2.2、行内元素2.3、行内块元素2.4、元素显示模式转换 3、字体属性3.1、font-family 字体3.2、font-size 字体大小3.3、fo…

【批量区域识别内容重命名】批量识别图片区域文字并重命名,批量图片部分识别内容重命文件,PDF区域识别提取重命名

我们在工作和生活中经常遇到这样的需求:比如将以下的图片区域识别进行重命名,批量识别后改成以时间和工作内容重命名,便于日后检索,快速查询 首先我们拍摄照片用到的是水印相机,这里的文字呢我们需要加个背景&#xff…

ARM与单片机有啥区别?

初学者必知:ARM与单片机到底有啥区别?1、软件方面这应该是最大的区别了。引入了操作系统。为什么引入操作系统?有什么好处嘛? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「ARM的资料从专业入门到高级教…

C语言练习——上三角矩阵

前言 今天我们来看看如何使用代码实现上三角矩阵吧。首先我们来了解一下上上三角矩阵是什么,上三角矩阵就是在矩阵从左上到右下的对角线之下的数组元素都为0的数组方矩阵,例如: 以一个三阶矩阵为例,在对角线元素之下,就…

【Hadoop】- YARN概述[6]

目录 一、YARN & Reduce 二、分布式资源调度 - YARN 1、资源调度 2、YARN的资源调度 总结 一、YARN & Reduce MapReduce是基于YARN运行的,即没有YARN “无法” 运行MapReduce程序。 二、分布式资源调度 - YARN YARN(Yet Another Resou…

springboot是什么?

可以应用于Web相关的应用开发。 选择合适的框架,去开发相关的功能,会有更高的效率。 为什么Spring Boot才是你该学的!学java找工作必会技能!在职程序员带你梳理JavaEE框架_哔哩哔哩_bilibili java工程师的必备技能 Spring是Java EE领域的企业级开发宽…

Golang汇编之通过map地址找到value的值

文章目录 背景gdb调试Go程序为什么不用dlvgdb调试Go可执行程序gdb打印地址内容 go汇编快速入门常用的寄存器和用法AMD64ARM64loong64riscv64 Go汇编常用命令及含义Go汇编和x86的区别找到map的赋值指令 Go中map的内存布局gdb中查看map结构map的存储结构map的内存布局计算bmap偏移…

【深度学习-番外1】Win10系统搭建VSCode+Anaconda+Pytorch+CUDA深度学习环境和框架全过程

专栏的老读者们都知道,以前的文章以使用MATLAB的为多。 不过后续陆续开始展开深度学习算法的应用,就会逐渐引入Python语言了(当然MATLAB的代码也会同步更新),这是由于在深度学习领域,Python应用更为广泛。…

uni-app为图片添加自定义水印(升级版)

前置内容 uni-app为图片添加自定义水印&#xff08;解决生成图片不全问题&#xff09; UI 升级 现在水印样式变成这样了&#xff1a; 代码 <template><canvas v-if"waterMarkParams.display" canvas-id"waterMarkCanvas" :style"canv…

如何使用JSONB类型在PostgreSQL中存储和查询复杂的数据结构?

文章目录 解决方案1. 创建包含JSONB列的表2. 插入JSONB数据3. 查询JSONB数据4. 创建索引以优化查询性能 示例代码结论 在PostgreSQL中&#xff0c;JSONB是一种二进制格式的JSON数据类型&#xff0c;它允许你在数据库中存储和查询复杂的JSON数据结构。与普通的JSON类型相比&…

Springboot的Test单元测试操作

Springboot的Test单元测试操作 简单总结需要操作的步骤 1&#xff0c;导入依赖 2&#xff0c;创建目录&#xff08;目录和启动类的目录保持一致&#xff09; 3&#xff0c;添加注解 4&#xff0c;写方法测试 1&#xff0c;导入依赖 <dependency><groupId>org.spri…