Android控件全解手册 - 任意View缩放平移工具-源码

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总
游戏脚本-辅助自动化Android控件全解手册再战Android系列
Scratch编程案例软考全系列Unity3D学习专栏
蓝桥系列ChatGPT和AIGC

👉关于作者

专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎底部卡片私我,交流让学习不再孤单

在这里插入图片描述

👉实践过程

GestureViewBinder

public class GestureViewBinder {private ScaleGestureBinder scaleGestureBinder;private ScrollGestureBinder scrollGestureBinder;private ScaleGestureListener scaleGestureListener;private ScrollGestureListener scrollGestureListener;private View targetView;private ViewGroup viewGroup;private boolean isScaleEnd = true;private OnScaleListener onScaleListener;private boolean isFullGroup = false;public static GestureViewBinder bind(Context context, ViewGroup viewGroup, View targetView) {return new GestureViewBinder(context, viewGroup, targetView);}private GestureViewBinder(Context context, ViewGroup viewGroup, View targetView) {this.targetView = targetView;this.viewGroup = viewGroup;scaleGestureListener = new ScaleGestureListener(targetView, viewGroup);scrollGestureListener = new ScrollGestureListener(targetView, viewGroup);scaleGestureBinder = new ScaleGestureBinder(context, scaleGestureListener);scrollGestureBinder = new ScrollGestureBinder(context, scrollGestureListener);targetView.setClickable(false);viewGroup.setOnTouchListener(new View.OnTouchListener() {@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getPointerCount() == 1 && isScaleEnd) {return scrollGestureBinder.onTouchEvent(event);} else if (event.getPointerCount() == 2 || !isScaleEnd) {isScaleEnd = event.getAction() == MotionEvent.ACTION_UP;if (isScaleEnd) {scaleGestureListener.onActionUp();}scrollGestureListener.setScale(scaleGestureListener.getScale());if (onScaleListener != null) {onScaleListener.onScale(scaleGestureListener.getScale());}return scaleGestureBinder.onTouchEvent(event);}return false;}});}private void fullGroup() {targetView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {targetView.getViewTreeObserver().removeOnPreDrawListener(this);float viewWidth = targetView.getWidth();float viewHeight = targetView.getHeight();float groupWidth = viewGroup.getWidth();float groupHeight = viewGroup.getHeight();ViewGroup.LayoutParams layoutParams = targetView.getLayoutParams();float widthFactor = groupWidth / viewWidth;float heightFactor = groupHeight / viewHeight;if (viewWidth < groupWidth && widthFactor * viewHeight <= groupHeight) {layoutParams.width = (int) groupWidth;layoutParams.height = (int) (widthFactor * viewHeight);} else if (viewHeight < groupHeight && heightFactor * viewWidth <= groupWidth) {layoutParams.height = (int) groupHeight;layoutParams.width = (int) (heightFactor * viewWidth);}targetView.setLayoutParams(layoutParams);return true;}});}public boolean isFullGroup() {return isFullGroup;}public void setFullGroup(boolean fullGroup) {isFullGroup = fullGroup;scaleGestureListener.setFullGroup(fullGroup);scrollGestureListener.setFullGroup(fullGroup);fullGroup();}public void setOnScaleListener(OnScaleListener onScaleListener) {this.onScaleListener = onScaleListener;}public interface OnScaleListener {void onScale(float scale);}
}

ScaleGestureBinder

public class ScaleGestureBinder extends ScaleGestureDetector {ScaleGestureBinder(Context context, ScaleGestureListener scaleGestureListener) {super(context, scaleGestureListener);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}}

ScaleGestureListener

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;}}
}

ScrollGestureBinder

class ScrollGestureBinder extends GestureDetector {ScrollGestureBinder(Context context, ScrollGestureListener scrollGestureListener) {super(context, scrollGestureListener);}
}

ScrollGestureListener

public class ScrollGestureListener extends GestureDetector.SimpleOnGestureListener {private float scale = 1;private View targetView;private ViewGroup viewGroup;private float distanceXTemp = 0;private float distanceYTemp = 0;private float viewWidthReal = 0;private float viewHeightReal = 0;private float viewWidthRealTemp = 0;private float viewHeightRealTemp = 0;private boolean isCalculate = false;private int viewWidthNormal = 0;private int viewHeightNormal = 0;private int groupWidth = 0;private int groupHeight = 0;private float maxTranslationLeft = 0;private float maxTranslationTop = 0;private float maxTranslationRight = 0;private float maxTranslationBottom = 0;private boolean isFullGroup = false;ScrollGestureListener(View targetView, ViewGroup viewGroup) {this.targetView = targetView;this.viewGroup = viewGroup;}@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);}}@Overridepublic boolean onDown(MotionEvent e) {//计算能移动的最大距离if (!isCalculate) {isCalculate = true;maxTranslationLeft = targetView.getLeft();maxTranslationTop = targetView.getTop();maxTranslationRight = viewGroup.getWidth() - targetView.getRight();maxTranslationBottom = viewGroup.getHeight() - targetView.getBottom();viewWidthNormal = targetView.getWidth();viewHeightNormal = targetView.getHeight();viewWidthRealTemp = viewWidthNormal;viewHeightRealTemp = viewHeightNormal;viewWidthReal = viewWidthNormal;viewHeightReal = viewHeightNormal;groupWidth = viewGroup.getWidth();groupHeight = viewGroup.getHeight();}return true;}void setScale(float scale) {viewWidthReal = viewWidthNormal * scale;viewHeightReal = viewHeightNormal * scale;//如果view比group小if (viewWidthReal < groupWidth) {if (isFullGroup) {distanceXTemp = 0;targetView.setTranslationX(0);}maxTranslationLeft = targetView.getLeft() - (viewWidthReal - viewWidthNormal) / 2;maxTranslationRight = (viewGroup.getWidth() - targetView.getRight()) - (viewWidthReal - viewWidthNormal) / 2;//如果移动距离超过最大可移动距离if (scale > this.scale && distanceXTemp < 0 && -distanceXTemp > maxTranslationLeft) {float translate = (viewWidthReal - viewWidthRealTemp) / 2;targetView.setTranslationX(targetView.getTranslationX() + translate);distanceXTemp = distanceXTemp + translate;} else if (scale > this.scale && distanceXTemp > 0 && distanceXTemp > maxTranslationRight) {float translate = (viewWidthReal - viewWidthRealTemp) / 2;targetView.setTranslationX(targetView.getTranslationX() - translate);distanceXTemp = distanceXTemp - translate;}} else {maxTranslationLeft = (viewWidthReal - viewWidthNormal) / 2 - (viewGroup.getWidth() - targetView.getRight());maxTranslationRight = (viewWidthReal - viewWidthNormal) / 2 - targetView.getLeft();if (scale < this.scale && distanceXTemp < 0 && -distanceXTemp > maxTranslationLeft) {float translate = (viewWidthRealTemp - viewWidthReal) / 2;targetView.setTranslationX(targetView.getTranslationX() + translate);distanceXTemp = distanceXTemp + translate;} else if (scale < this.scale && distanceXTemp > 0 && distanceXTemp > maxTranslationRight) {float translate = (viewWidthRealTemp - viewWidthReal) / 2;targetView.setTranslationX(targetView.getTranslationX() - translate);distanceXTemp = distanceXTemp - translate;}}if (viewHeightReal < groupHeight) {maxTranslationTop = targetView.getTop() - (viewHeightReal - viewHeightNormal) / 2;maxTranslationBottom = (viewGroup.getHeight() - targetView.getBottom()) - (viewHeightReal - viewHeightNormal) / 2;if (isFullGroup) {distanceYTemp = 0;targetView.setTranslationY(0);}//如果移动距离超过最大可移动距离if (scale > this.scale && distanceYTemp < 0 && -distanceYTemp > maxTranslationTop) {float translate = (viewHeightReal - viewHeightRealTemp) / 2;targetView.setTranslationY(targetView.getTranslationY() + translate);distanceYTemp = distanceYTemp + translate;} else if (scale > this.scale && distanceYTemp > 0 && distanceYTemp > maxTranslationBottom) {float translate = (viewHeightReal - viewHeightRealTemp) / 2;targetView.setTranslationY(targetView.getTranslationY() - translate);distanceYTemp = distanceYTemp - translate;}} else {maxTranslationTop = (viewHeightReal - viewHeightNormal) / 2 - (viewGroup.getHeight() - targetView.getBottom());maxTranslationBottom = (viewHeightReal - viewHeightNormal) / 2 - targetView.getTop();if (scale < this.scale && distanceYTemp < 0 && -distanceYTemp > maxTranslationTop) {float translate = (viewHeightRealTemp - viewHeightReal) / 2;targetView.setTranslationY(targetView.getTranslationY() + translate);distanceYTemp = distanceYTemp + translate;} else if (scale < this.scale && distanceYTemp > 0 && distanceYTemp > maxTranslationBottom) {float translate = (viewHeightRealTemp - viewHeightReal) / 2;targetView.setTranslationY(targetView.getTranslationY() - translate);distanceYTemp = distanceYTemp - translate;}}viewWidthRealTemp = viewWidthReal;viewHeightRealTemp = viewHeightReal;this.scale = scale;}@Overridepublic boolean onSingleTapUp(MotionEvent e) {float left = viewWidthReal > groupWidth ? 0 : (targetView.getLeft() - ((viewWidthReal - viewWidthNormal) / 2));float top = viewHeightReal > groupHeight ? 0 : (targetView.getTop() - ((viewHeightReal - viewHeightNormal) / 2));float right = viewWidthReal > groupWidth ? groupWidth : viewGroup.getWidth() - ((viewGroup.getWidth() - targetView.getRight()) - (viewWidthReal - viewWidthNormal) / 2);float bottom = viewHeightReal > groupHeight ? groupHeight : viewGroup.getHeight() - ((viewGroup.getHeight() - targetView.getBottom()) - (viewHeightReal - viewHeightNormal) / 2);RectF rectF = new RectF(left, top, right, bottom);if (rectF.contains(e.getX(), e.getY())) {targetView.performClick();}return super.onSingleTapUp(e);}public boolean isFullGroup() {return isFullGroup;}void setFullGroup(boolean fullGroup) {isFullGroup = fullGroup;}
}

👉其他

📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

温馨提示点击下方卡片获取更多意想不到的资源。
空名先生

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

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

相关文章

Nginx系列-正向代理和反向代理

Nginx系列-正向代理和反向代理 文章目录 Nginx系列-正向代理和反向代理1. 三个对象2. 两种场景代理2.1. 正向代理2.2. 反向代理 3. 两种场景的对比3.1 为什么叫做反向代理3.2 正向代理和反向代理的作用 1. 三个对象 客户端&#xff1a;发出请求到代理&#xff0c;并接收代理的…

一文搞定XMLHttpRequest,AJAX,Promise,Axios及操作实战

XMLHttpRequest,AJAX,Promise,Axios都是发送异步请求的工具&#xff0c;只是使用的场合和方式有所不同。都是一种用于创建快速动态网页的技术 1、认识同步请求和异步请求&#xff1f; 1.1、认识同步请求&#xff1f; 1、我们点击淘宝首页的男装&#xff0c;进入男装页面的这…

猜数字游戏

需求目标 这个游戏窗口要求玩家猜一个1到100之间的数字。玩家可以在文本框中输入自己的猜测&#xff0c;并点击提交按钮进行验证。游戏会给出相应的提示&#xff0c;直到玩家猜中正确的数字为止。 效果 源码 /*** author lwh* date 2023/11/28* description 猜数字游戏**/ i…

采集工具-免费采集器下载

在当今信息时代&#xff0c;互联网已成为人们获取信息的主要渠道之一。对于研究者和开发者来说&#xff0c;如何快速准确地采集整个网站数据是至关重要的一环。以下将从九个方面详细探讨这一问题。 确定采集目标 在着手采集之前&#xff0c;明确目标至关重要。这有助于确定采集…

Linux ps命令详解:如何查看进程的PID、占用的CPU和内存使用率、虚拟内存大小等信息(附实例教程和注意事项)

Linux ps命令介绍 Linux ps命令&#xff0c;全称为process status&#xff0c;是一个非常实用的命令&#xff0c;用于显示当前进程的状态。它的功能类似于Windows的任务管理器。通过ps命令&#xff0c;我们可以查看到进程的PID、占用的CPU和内存使用率、虚拟内存大小、实际内存…

C++数据结构:图

目录 一. 图的基本概念 二. 图的存储结构 2.1 邻接矩阵 2.2 邻接表 三. 图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四. 最小生成树 4.1 最小生成树获取策略 4.2 Kruskal算法 4.3 Prim算法 五. 最短路径问题 5.1 Dijkstra算法 5.2 Bellman-Ford算法 5.3 Floyd-…

零信任安全:远程浏览器隔离(RBI)的重要性

引言 在当今数字化时代&#xff0c;网络安全已成为个人和企业关注的焦点。随着网络攻击和恶意软件的不断增加&#xff0c;远程浏览器隔离(RBI)SAAS系统变得至关重要。本文将深入探讨远程浏览器隔离系统的重要性&#xff0c;以及它如何帮助用户保护其网络免受恶意软件和网络攻击…

5V摄像机镜头驱动IC GC6208,可用于摄像机,机器人等产品中可替代AN41908

GC6208是一个镜头电机驱动IC摄像机和安全摄像机。该设备集成了一个直流电机驱动器的Iris的PID控制系统&#xff0c;也有两个通道的STM电机驱动器的变焦和对焦控制。 芯片的特点: 内置用于Iris控制器的直流电机驱动器 内置2个STM驱动程序&#xff0c;用于缩放和…

离散数学-集合论基础

3.1集合的基本概念 1&#xff09;集合及元素 2&#xff09;集合的表示 3&#xff09;集合的关系 4&#xff09;特殊集合 3.2集合的运算 并、交、差、对称差 3.3集合的划分与覆盖 3.4排斥包含管理 3.1集合的基本概念 1&#xff09;集合及元素 将某种具有同种属性的个体…

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

原创/朱季谦 阅读Dubbo源码过程中&#xff0c;会发现&#xff0c;Dubbo消费端在做远程调用时&#xff0c;默认通过 Javassist 框架为服务接口生成动态代理类&#xff0c;调用javassist框架下的JavassistProxyFactory类的getProxy(Invoker invoker, Class<?>[] interfac…

如何使用企业微信 WorkTool API 开源框架快速开发企微聊天机器人(详细教程)

WorkTool 基本框架概述 WorkTool 是一个依附于企业微信来运行的无人值守群管理机器人程序&#xff0c;WorkTool 开源&#xff0c;并且永久免费。您可以使用本应用程序来自动执行一个自己企业微信里的账号&#xff08;当做机器人账号&#xff09;可通过后台调用对应的 API 来驱…

【pytorch】从yolo的make_grid理解torch.meshgrid、torch.stack

文章目录 简述1、torch.meshgrid 创建行列坐标2、torch.stack 结合行列坐标3、通过view函数扩展维度 简述 yolo检测 make_grid创建网格代码如下&#xff0c;那么什么是torch.meshgrid? def _make_grid(nx20, ny20):yv, xv torch.meshgrid([torch.arange(ny), torch.arange(…