由于项目的需要,自定义个view,控制父控件,既可以缩放放大,滑动边界检测。自己实现了通过父控件就能操作子控件的自定义view,直接引用就可以使用。

下面是我实现的一个思路,贴了部分代码,大家可以参考。具体的核心代码我都上传到了我的github上了,大家可以下载试试,感觉好的话,大家给个star

demo下载

在MainActivity调用这个方法去初始化就可以了 :

     //parentView对应的是父控件,groupView对应的是子控件GestureViewManager bind = GestureViewManager.bind(this, groupView, parentView);

缩放放大手势

这块我主要是继承原生的ScaleGestureDetector并实现OnScaleGestureListener的事件去处理的。

  • 1、在缩放的同时获取detector.getScaleFactor()的值,由于控件大小不停在改变,所以该值会出现误差导致比例出现异常,因为缩放平移肯定需要有一个边界,所以目前我通过外面包裹ViewGroup,通过给ViewGruop设置手势的方式解决这个问题。因为外面的ViewGroup大小是不会改变的,所以系统计算的比例不会出现问题。有一个ViewGruop也符合我们的需求。
  • 2、如果View为可点击的View(Button)或我们给它设置了点击事件,这时View是没办法再监听缩放手势的,我们需要额外处理一下,在缩放手势执行前屏蔽点击事件,在结束后再设置允许点击。
  • 3、detector.getScaleFactor()得到的缩放比例都是相对于目前view的大小进行计算的,而我们缩放view时,view的比例都是从原始大小开始的,所以我们必须记录上次缩放的比例,下次开始缩放时,从上次的比例大小开始缩放。

上面的三点是我通过查资料总结的方案,下面是我实现的代码

/*** Created by wdh.* Description :放大缩放手势的监听器*/public class ScaleGestureListener implements ScaleGestureDetector.OnScaleGestureListener/*, GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener */ {private View targetView;private float scale = 1;private float scaleTemp = 1;private boolean isFullGroup = false;ScaleGestureListener(View targetView, ViewGroup viewGroup) {this.targetView = targetView;}@Overridepublic boolean onScale(ScaleGestureDetector detector) {scale = scaleTemp * detector.getScaleFactor();targetView.setScaleX(scale);targetView.setScaleY(scale);return false;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {return true;}@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {scaleTemp = scale;}float getScale() {return scale;}public boolean isFullGroup() {return isFullGroup;}void setFullGroup(boolean fullGroup) {isFullGroup = fullGroup;}void onActionUp() {if (isFullGroup && scaleTemp < 1) {scale = 1;targetView.setScaleX(scale);targetView.setScaleY(scale);scaleTemp = scale;}}
}

到这里就基本实现了缩放和放大的功能,很简单。

2、平移的手势以及移动边界计算

这块我也是用的原生的控件去处理的GestureDetector,并继承SimpleOnGestureListener的监听事件

  • view大小是不能小于viewGroup的大小的,小于group会回弹到充满viewGroup(后面改成了可选设置)。
  • view小于group大小时需要居中显示。并且缩放时,如果view不在中心,需要虽然比例慢慢回到中心。
  • 放大平移时,不能移出group边界。
  • 滑动和缩放的手势会起冲突,无法同时监听。所以在控件的onTouchEvent方法中,我们需要自己处理一下,我这里是通过判断按在屏幕上的手指数量,来返回不同手势回调的。一根手指按下,则为滑动手势,两根手指,则为缩放手势。
  • 接下来就是计算边界,我们先不考虑缩放的情况,只考虑控件本身可移动的大小。能够移动的距离分别为控件距左、上、右、下的距离。也就是,如果控件向左移动,则判断控件距离左边的距离是否大于0,如果大于0,才允许向左移动。以此类推上、右和下。如下图

    通过上面的需求,下面是我的主要代码处理
/*** Description :滑动手势的监听器*/public class ScrollGestureListener extends GestureDetector.SimpleOnGestureListener {
@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {distanceX = -distanceX;distanceY = -distanceY;if (isFullGroup || scale > 1) {if (viewWidthReal > groupWidth) {translationXOnScrollEvent(distanceX);}if (viewHeightReal > groupHeight) {translationYOnScrollEvent(distanceY);}} else {translationXOnScrollEvent(distanceX);translationYOnScrollEvent(distanceY);}return super.onScroll(e1, e2, distanceX, distanceY);}private void translationXOnScrollEvent(float distanceX) {//最大移动距离全部为正数,所以需要通过判断distanceX的正负,来判断是向左移动还是向右移动,// 然后通过取distanceX的绝对值来和相应移动方向的最大移动距离比较if ((distanceX < 0 && Math.abs(distanceXTemp + distanceX) < maxTranslationLeft)|| (distanceX > 0 && distanceXTemp + distanceX < maxTranslationRight)) {distanceXTemp += distanceX;targetView.setTranslationX(distanceXTemp);//如果超出边界,就移动到最大距离,防止边界有剩余量} else if ((distanceX < 0 && Math.abs(distanceXTemp + distanceX) > maxTranslationLeft)) {distanceXTemp = -maxTranslationLeft;targetView.setTranslationX(-maxTranslationLeft);} else if ((distanceX > 0 && distanceXTemp + distanceX > maxTranslationRight)) {distanceXTemp = maxTranslationRight;targetView.setTranslationX(maxTranslationRight);}}private void translationYOnScrollEvent(float distanceY) {if ((distanceY < 0 && Math.abs(distanceYTemp + distanceY) < maxTranslationTop)|| (distanceY > 0 && distanceYTemp + distanceY < maxTranslationBottom)) {distanceYTemp += distanceY;targetView.setTranslationY(distanceYTemp);//如果超出边界,就移动到最大距离,防止边界有剩余量} else if ((distanceY < 0 && Math.abs(distanceYTemp + distanceY) > maxTranslationTop)) {distanceYTemp = -maxTranslationTop;targetView.setTranslationY(-maxTranslationTop);} else if ((distanceY > 0 && distanceYTemp + distanceY > maxTranslationBottom)) {distanceYTemp = maxTranslationBottom;targetView.setTranslationY(maxTranslationBottom);}}

android 自定义view,缩放放大,平移边界检测相关推荐

  1. Android 自定义view 图片编辑(画圆,画长方形,手势缩放)

    Android 自定义view 图片编辑(画圆,画长方形,手势缩放) package com.bridgetek.yqm.view; import android.annotation.Suppres ...

  2. Android 自定义View —— Canvas

    上一篇在android 自定义view Paint 里面 说了几种常见的Point 属性 绘制图形的时候下面总有一个canvas ,Canvas 是是画布 上面可以绘制点,线,正方形,圆,等等,需要和 ...

  3. android代码实现手机加速功能,Android自定义View实现内存清理加速球效果

    Android自定义View实现内存清理加速球效果 发布时间:2020-09-21 22:21:57 来源:脚本之家 阅读:105 作者:程序员的自我反思 前言 用过猎豹清理大师或者相类似的安全软件, ...

  4. 【5年Android从零复盘系列之二十】Android自定义View(15):Matrix详解(图文)【转载】

    [转载]本文转载自麻花儿wt 的文章<android matrix 最全方法详解与进阶(完整篇)> [5年Android从零复盘系列之二十]Android自定义View(15):Matri ...

  5. Android自定义View分享——仿微信朋友圈图片合并效果

    写在前面 笔者近来在学习Android自定义View,收集了一些不算复杂但又"长得"还可以的自定义View效果实现,之前分享过两个效果:一个水平的进度条,一个圆形温度显示器,如果你 ...

  6. Android 抖音爱心动画,Android自定义View实现抖音飘动红心效果

    本文实例为大家分享了Android自定义View实现抖音飘动红心效果的具体代码,供大家参考,具体内容如下 自定义View--抖音飘动红心 效果展示 动画效果 使用自定义view完成红心飘动效果 Vie ...

  7. android 自定义View 视差动画

    本系列自定义View全部采用kt **系统: **mac android studio: 4.1.3 **kotlin version:**1.5.0 gradle: gradle-6.5-bin.z ...

  8. Android自定义View之Paint绘制文字和线

    Android自定义View系列 Android自定义View注意事项 Android自定义View之图像的色彩处理 Android自定义View之Canvas Android自定义View之轻松实现 ...

  9. android+直播点赞,Android自定义View实现直播点赞特效的方法

    Android自定义View实现直播点赞特效的方法 发布时间:2020-07-30 09:24:13 来源:亿速云 阅读:77 作者:小猪 这篇文章主要讲解了Android自定义View实现直播点赞特 ...

  10. android 自定义红心,Android自定义View实现抖音飘动红心效果

    本文实例为大家分享了Android自定义View实现抖音飘动红心效果的具体代码,供大家参考,具体内容如下 自定义View--抖音飘动红心 效果展示 动画效果 使用自定义view完成红心飘动效果 Vie ...

最新文章

  1. springboot 没有跳转到指定页面
  2. C语言-运算符优先级及注意事项
  3. OCM备考 一、Server config 之管理表空间
  4. 不信你不来!周老师带你用ArkControl实现自动化运维体系建设
  5. css33d坐标系,CSS3-3D技术
  6. 西北师范大学知行学院计算机科学与技术,西北师范大学知行学院电子信息工程专业...
  7. Eclipse用法和技巧七:自动生成get和set方法2
  8. VMware报错“锁定文件失败“解决方法
  9. [转载] 在IPython中重新加载模块 importlib
  10. 可变长参数以及面试题
  11. 关于ext4 simg fill chunk type
  12. 一级 计算机应用基础,一级计算机应用基础(教材浓缩精华版)
  13. 需要编程资料(java、php、python、js、vue)、SS账号、或者mac破解软件的戳
  14. 实用性室内地图导航软件
  15. [翻译]CryEngine3中ClothShader详解
  16. metasploit的SET的Credential Harvester Attack Method
  17. 交换机短路_交换机环路发现及处理
  18. 【转帖】赤壁之战,曹操大败只因缺了Service Mesh
  19. RationalDMIS 7.0量块程序(力合)
  20. linux ramdisk swap,ramdisk和initramfs比较

热门文章

  1. 【刷题】BZOJ 4827 [Hnoi2017]礼物
  2. linux下crossover打开软件,CrossOver for Linux
  3. 无双卡刀常见问题总结
  4. python爬取英雄联盟所有皮肤_用Python爬取英雄联盟(lol)全部皮肤
  5. appserv的使用
  6. 人肉工程在机器学习实践中的作用
  7. Centos7.6上mhvtl 虚拟带库配置
  8. mysql Exception及其解决方案(持续更新中)
  9. 别让梦想阻碍你的成功
  10. 哔哩哔哩android课程,哔哩哔哩连续包月大会员怎么取消?苹果安卓取消连续包月方法...