0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙系统的手势操控组件代码现已开源

OpenHarmony技术社区 ? 来源:鸿蒙技术社区 ? 作者:朱伟ISRC ? 2021-06-24 18:16 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

基于安卓平台的手势操控组件 PinchImageView-ohos,实现鸿蒙的功能化迁移和重构。代码已经开源,欢迎各位开发者提出宝贵意见。

开源地址:

https://gitee.com/isrc_ohos/pinch-image-view-ohos

PinchImageView-ohos 是一个支持多点触控的 ImageView 手势操控组件,通过识别单指双击、双指捏合、单指滑动等手势指令,实现图片的放大、缩小、滑动等效果。

该组件功能丰富且使用简单,被广泛应用于各类图片预览类应用。

01

组件效果展示

①双指相向或相对捏合,实现图片的缩放变化。

②单指双击实现图片的放大缩小。

③单指双击后单指移动,实现图片的放大后平移。

02

Sample 解析

Sample 部分主要负责整体显示布局的搭建。首先为 PinchImageView-ohos 组件设置显示图片,然后将组件对象添加到显示布局中。

下面将详细介绍组件的使用方法:

步骤 1:创建整体的显示布局。

步骤 2:导入相关类并实例化 PinchImageView-ohos 组件对象。

步骤 3:设置显示图片。

步骤 4:将 PinchImageView-ohos 组件对象添加到整体显示布局中。

//步骤1 创建整体的显示布局

DirectionalLayout directionalLayout = new DirectionalLayout(this);

//步骤2 导入相关类并实例化对象

PinchImageViewnew pinchImageView = new PinchImageViewnew(this);

//步骤3 设置显示图片

pinchImageView.setPixelMap(this, ResourceTable.Media_1111);

//步骤4 将pinchImageView添加到整体显示布局中

directionalLayout.addComponent(pinchImageView);

setUIContent(directionalLayout);

03

Library 解析

Library 主要为 PinchImageView-ohos 组件实现手势获取功能和图片操控功能。

开发者通过设置监听器来捕捉各类手势,根据不同的手势执行不同的图片操控方法,从而显示不同的图片操控效果,如放大、缩小、移动。

①手势获取方法

手势获取对实现 PinchImageView-ohos 组件的功能尤为重要,此处主要通过 onTouchEvent() 方法来捕捉对应的手势。

主要用到的手势包含:

PRIMARY_POINT_UP(最后一根手指从屏幕上抬起)

PRIMARY_POINT_DOWN(第一根手指触摸屏幕)

OTHER_POINT_DOWN(当一根或多根手指已经触摸屏幕时,另一个手指触摸屏幕 )

OTHER_POINT_UP(一些手指从屏幕上抬起,而一些手指仍留在屏幕上 )

POINT_MOVE(手指在屏幕上移动)

通过监控各类手势的操作顺序和触碰时间等条件,达到识别捏合、滑动、单击、双击等复杂手势的效果。

onTouchEvent() 函数首先通过 TouchEvent.getAction() 方法获取当前的手势,当手势为:

(1)PRIMARY_POINT_UP

需要判断图片之前是否处于缩放模式(此时图片处于缩放状态)。如果是缩放模式,则触发结束缩放动画,后将手势状态置于自由模式。

//最后一个点抬起或者取消,结束所有模式if (action == TouchEvent.PRIMARY_POINT_UP || action == TouchEvent.CANCEL) {

//如果之前是缩放模式,还需要结束缩放动画

if (mPinchMode == PINCH_MODE_SCALE) {

scaleEnd();//缩放结束

}

//手势状态置于自由模式

mPinchMode = PINCH_MODE_FREE;

}

(2)PRIMARY_POINT_DOWN

需要判断图片是否在缩放动画中,若不在,图片将切换到滚动模式(此时图片处于可自由移动状态),并保存触发点的位置,用于(5)中的计算。

else if (action == TouchEvent.PRIMARY_POINT_DOWN) {

//在缩放动画过程中不允许启动滚动模式

if (!(mScaleAnimator != null && mScaleAnimator.isRunning())) {

//在动画过程中不允许启动滚动模式,停止所有动画

cancelAllAnimator();

//切换到滚动模式

mPinchMode = PINCH_MODE_SCROLL;

//保存触发点的位置用于(5)中的计算

mLastMovePoint.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY());

}

}

(3)OTHER_POINT_DOWN

需要将图片模式切换到缩放模式,并保存两个触发点的位置,用于(5)中的计算。

else if (action == TouchEvent.OTHER_POINT_DOWN) {

//在动画过程中不允许启动缩放模式,停止所有动画

cancelAllAnimator();

//切换到缩放模式

mPinchMode = PINCH_MODE_SCALE;

//保存缩放的两个触发点的位置,用于(5)中的计算

saveScaleContext(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY());

}

(4)OTHER_POINT_UP

需要判断手指抬起后图片是否处于缩放模式。如果处于缩放模式下,判断识别到的手指是否超过两个。

在剩余手指超过两个(缩放模式未结束)的情况下,第一个触摸的手指抬起,那么让第二个触摸的手指和第三个触摸的手指所在的点作为缩放控制点。

在剩余手指超过两个(缩放模式未结束)的情况下,第二个触摸的手指抬起,那么让第一个触摸的手指和第三个触摸的手指所在的点作为缩放控制点。

如果处于缩放模式下,判断识别到的手指只有一个。此时不能允许它切换到滚动模式,因为图片可能没有在初始的位置上。

手指抬起后图片未处于缩放模式时(屏幕上仅剩余一个手指),开启滚动模式,并记录开始滚动的点。

else if (action == TouchEvent.OTHER_POINT_UP) {

//多个手指情况下抬起一个手指,此时需要是缩放模式才触发

if (mPinchMode == PINCH_MODE_SCALE) {

//抬起的点如果大于2,那么缩放模式还有效,但是有可能初始点变了,重新测量初始点

if (event.getPointerCount() 》 2) {

//如果还没结束缩放模式,但是第一个点抬起了,那么让第二个点和第三个点作为缩放控制点

if (event.getAction() 》》 8 == 0) {

event.getPointerPosition(1).getX();

saveScaleContext(event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY(), event.getPointerPosition(2).getX(), event.getPointerPosition(2).getY());

//如果还没结束缩放模式,但是第二个点抬起了,那么让第一个点和第三个点作为缩放控制点

} else if (event.getAction() 》》 8 == 1) {

saveScaleContext(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(2).getX(), event.getPointerPosition(2).getY());

}

}

//如果抬起的点等于2,那么此时只剩下一个点,也不允许进入单指模式,因为此时可能图片没有在正确的位置上

}

}

(5)POINT_MOVE

需要判断当前图片的模式。当为滚动模式时,执行 scrollBy() 方法来实现图片的移动效果;当它为缩放模式时,计算两个缩放点的距离和缩放点的中心,并执行 scale() 方法实现图片的缩放效果。

scrollBy() 方法和 scale() 方法的具体逻辑在图片操控方法中有详细介绍,此处就不做过多赘述。

else if (action == TouchEvent.POINT_MOVE) {

if (!(mScaleAnimator != null && mScaleAnimator.isRunning())) {

//在滚动模式下移动

if (mPinchMode == PINCH_MODE_SCROLL) {

//每次移动产生一个差值累积到图片位置上

scrollBy(event.getPointerPosition(0).getX() - mLastMovePoint.position[0], event.getPointerPosition(0).getY() - mLastMovePoint.position[1]);

//记录新的移动点

mLastMovePoint.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY());

//在缩放模式下移动

} else if (mPinchMode == PINCH_MODE_SCALE && event.getPointerCount() 》 1) {

//两个缩放点间的距离

float distance = MathUtils.getDistance(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY());

//保存缩放点中心

float[] lineCenter = MathUtils.getCenterPoint(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY());

mLastMovePoint.modify(lineCenter[0], lineCenter[1]);

//处理缩放

scale(mScaleCenter, mScaleBase, distance, mLastMovePoint);

}

}

}

②图片操控方法

1、图片缩放

双指捏合:顾名思义是表示两根手指向相反方向移动的操作,该操作可实现图片放大缩小的效果。双指捏合完成图片缩放的功能是由 scale() 方法实现的。

在 scale() 方法体中需要设置各种缩放参数:scaleBase 是缩放系数、scaleCenter 代表图片缩放中点、distance 指两指间距离、lineCenter 是两指中点。

scaleBase 和 distance 相乘会得到缩放比例,图片依旧缩放比例进行变化。

在缩放过程中,图片缩放中点 scaleCenter 会跟随两指中点 lineCenter 移动,实现以两指中点为中心对图片进行放大缩小的效果,缩放效果如图 4 所示。图 4:图片双指缩放

private void scale(Point scaleCenter, float scaleBase, float distance, Point lineCenter) {

if (!isReady()) {

return;

}

//计算图片从fit center状态到目标状态的缩放比例

float scale = scaleBase * distance;

Matrix matrix = MathUtils.matrixTake();

//按照图片缩放中心缩放,并且让缩放中心在缩放点中点上

matrix.postScale(scale, scale, scaleCenter.position[0], scaleCenter.position[1]);

//让图片的缩放中点跟随手指缩放中点

matrix.postTranslate(lineCenter.position[0] - scaleCenter.position[0], lineCenter.position[1] - scaleCenter.position[1]);

//应用变换

mOuterMatrix.setMatrix(matrix);

MathUtils.matrixGiven(matrix);

dispatchOuterMatrixChanged();

//重绘

invalidate();

}

单指双击:表示用单根手指双击屏幕的操作,该操作可实现图片放大缩小的效果,单指双击完成图片缩放的功能是由 doubleTap() 方法实现的。

在 doubleTap() 方法体中我们初始化了一个缩放动画的对象 mScaleAnimator(),它有两个参数分别为 mOuterMatrix(开始矩阵)和 animEnd(结束矩阵)。

开始矩阵表示图片原来的位置与大小;结束矩阵表示图片缩放后的位置与大小,是根据放大比例和双击点位置确定的。

确定图片的开始和结束矩阵后,启动缩放动画,便可以实现缩放效果,如图 5 所示:

private void doubleTap(float x, float y) {

...

//开始计算缩放动画的结果矩阵

Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);

//计算还需缩放的倍数

animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);

//将放大点移动到控件中心

animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y);

RectFloat testBound = MathUtils.rectFTake(0,0,mp.getImageInfo().size.width,mp.getImageInfo().size.height);

...

//清理当前可能正在执行的动画

cancelAllAnimator();

//启动矩阵动画

mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);

mScaleAnimator.start();

...

}

2、图片在缩放状态下移动

单指滑动表示手指在屏幕上完成矢量平移,是图片移动的唯一方式。该功能是通过 scrollBy() 方法实现的。

以实现图片左右移动为例,在 scrollBy() 方法中,需要判断缩放状态下图片位移的最大距离,有以下几种不同的情况:

图片移动后,左侧边缘超出控件的左侧边缘,图片无法移动。

图片移动后,右侧边缘超出控件的右侧边缘,图片无法移动。

图片移动后,两侧都未超出控件边缘的情况下,将以手指触碰点作为控制点,对图片进行水平移动。

图片上下平移的情况与左右平移类似,这里不做赘述,图片移动效果如图 6 所示:

图 6:图片移动的最大距离

public boolean scrollBy(float xDiff, float yDiff) {

...

if (bound.right - bound.left 《 displayWidth) {

xDiff = 0;

//如果图片左边在移动后超出控件左边

} else if (bound.left + xDiff 》 0) {

//如果在移动之前是没超出的,计算应该移动的距离

if (bound.left 《 0) {

xDiff = -bound.left;

//否则无法移动

} else {

xDiff = 0;

}

//如果图片右边在移动后超出控件右边

} else if (bound.right + xDiff 《 displayWidth) {

//如果在移动之前是没超出的,计算应该移动的距离

if (bound.right 》 displayWidth) {

xDiff = displayWidth - bound.right;

//否则无法移动

} else {

xDiff = 0;

}

}

...

}

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 操作系统
    +关注

    关注

    37

    文章

    7191

    浏览量

    126232
  • 鸿蒙系统
    +关注

    关注

    183

    文章

    2642

    浏览量

    68400
  • HarmonyOS
    +关注

    关注

    80

    文章

    2130

    浏览量

    33670

原文标题:鸿蒙手势操控组件,代码已开源!

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    鸿蒙非侵入式弹窗新解法,企查查正式开源“QuickDialog”弹窗组件

    近日,企查查将其自研的鸿蒙弹窗组件库“QuickDialog”开源,并上线至?OpenHarmony 三方库中心仓。这是鸿蒙生态首个支持“弹窗堆栈暂存能力”的非侵入式弹窗解决方案,凭借
    的头像 发表于 07-31 10:40 ?226次阅读
    <b class='flag-5'>鸿蒙</b>非侵入式弹窗新解法,企查查正式<b class='flag-5'>开源</b>“QuickDialog”弹窗<b class='flag-5'>组件</b>库

    【HarmonyOS 5】金融应用开发鸿蒙组件实践

    【HarmonyOS 5】金融应用开发鸿蒙组件实践 ##鸿蒙开发能力 ##HarmonyOS SDK应用服务##鸿蒙金融类应用 (金融理财# 一、鸿
    的头像 发表于 07-11 18:20 ?372次阅读
    【HarmonyOS 5】金融应用开发<b class='flag-5'>鸿蒙</b><b class='flag-5'>组件</b>实践

    开源鸿蒙应用技术组件共建计划启动

    近日,开源鸿蒙开发者大会2025(OHDC.2025,以下简称“大会”)在深圳成功举办。开源四年多来,开源鸿蒙
    的头像 发表于 06-05 14:33 ?541次阅读

    开源鸿蒙操作系统的生态成果与落地实践

    电网、中国科学院软件研究所、证通电子等合作单位共同支持。本次大会聚焦开源鸿蒙 5.1 Release版本,面向开发者和伙伴深度展示开源鸿蒙操作系统
    的头像 发表于 06-05 14:27 ?631次阅读

    Kuikly鸿蒙版正式开源 —— 揭秘卓越性能适配之旅

    系统化工作,同时为了达到高性能、原生渲染、动态化等适配目标,进行了持续的探索和优化。其核心适配工作包括:对接鸿蒙UI系统,封装原子组件,对接事件
    发表于 06-04 16:46

    润和软件旗下润开鸿亮相开源鸿蒙开发者大会2025

    近日,开源鸿蒙开发者大会2025(OHDC.2025)于深圳再启新篇,会上正式发布了开源鸿蒙5.1 Release版本,并进行开源
    的头像 发表于 06-03 16:22 ?746次阅读

    迅龙软件应邀出席开源鸿蒙开发者大会2025,AI分论坛发表主旨演讲

    5月24日,开源鸿蒙开发者大会2025(OHDC.2025)在深圳隆重开幕。会上正式发布了开源鸿蒙5.1Release版本,并进行开源
    的头像 发表于 05-28 16:05 ?505次阅读
    迅龙软件应邀出席<b class='flag-5'>开源</b><b class='flag-5'>鸿蒙</b>开发者大会2025,AI分论坛发表主旨演讲

    2025开源鸿蒙开发者大会圆满落幕

    近日,开源鸿蒙开发者大会2025(OHDC.2025,简称“大会”)在深圳隆重开幕。大会正式发布了开源鸿蒙5.1 Release版本,举行了开源
    的头像 发表于 05-26 17:03 ?707次阅读

    开源鸿蒙之城”生态新高地:全国首家省级开源鸿蒙制造业创新中心落户深圳前海

    名单,“广东省开源鸿蒙智能物联网创新中心”在列,牵头单位为深开鸿、深圳中软国际科技服务有限公司。该中心将围绕开源鸿蒙(OpenHarmony)操作
    的头像 发表于 05-14 15:42 ?463次阅读
    “<b class='flag-5'>开源</b><b class='flag-5'>鸿蒙</b>之城”生态新高地:全国首家省级<b class='flag-5'>开源</b><b class='flag-5'>鸿蒙</b>制造业创新中心落户深圳前海

    DialogHub上线OpenHarmony开源社区,高效开发鸿蒙应用弹窗

    应用中,“DialogHub”的能力也得到了开发者的高度认可。据某头部App开发者反馈:“DialogHub”对系统弹窗进行了统一封装,链式调用学习成本低,一行代码就能完成弹窗属性配置,代码更加简洁清晰
    发表于 04-03 17:30

    【贝启科技BQ3568HM开源鸿蒙开发板深度试用报告】系统镜像编译和烧录

    于进行图形界面应用的开发。贝启科技BQ3568HM开源鸿蒙开发板配备了显示屏,可以开发GUI应用。 一、系统镜像编译 参考 BQ3568_代码下载-
    发表于 03-16 10:53

    开源啦!!!基于鸿蒙ArkTS封装的图表组件《McCharts》,大家快来一起共创

    的地方请大家高抬贵手,宽容一下,谢谢。 这次主要是给大家带来一个重磅消息,就是我自己使用鸿蒙ArkTS语法开发的图表组件今日正式开源了。为什么?原因有两点吧! 鸿蒙是国产的操作
    发表于 03-15 15:21

    开源大师兄怎么刷鸿蒙系统的,那些传感器配件还能调用吗

    开源大师兄怎么刷鸿蒙系统的,那些传感器配件还能调用吗
    发表于 01-03 14:32

    开源鸿蒙荣获开放原子“2024年度操作系统领域国内活跃开源项目”

    开源鸿蒙”或“OpenHarmony”)荣获“2024年度操作系统领域国内活跃开源项目”。 活跃的开源项目是
    的头像 发表于 12-28 15:39 ?994次阅读

    开源鸿蒙操作系统5.0 Release版本发布

    开源鸿蒙操作系统5.0 Release版本。 该版本在系统完备度、分布式创新、开发者体验以及系统稳定性等方面均实现了显著提升,标志着
    的头像 发表于 12-23 11:35 ?2510次阅读