Android怎么实现橡皮筋回弹和平移缩放效果
发表于:2025-01-21 作者:千家信息网编辑
千家信息网最后更新 2025年01月21日,这篇文章主要介绍"Android怎么实现橡皮筋回弹和平移缩放效果",在日常操作中,相信很多人在Android怎么实现橡皮筋回弹和平移缩放效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法
千家信息网最后更新 2025年01月21日Android怎么实现橡皮筋回弹和平移缩放效果
这篇文章主要介绍"Android怎么实现橡皮筋回弹和平移缩放效果",在日常操作中,相信很多人在Android怎么实现橡皮筋回弹和平移缩放效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Android怎么实现橡皮筋回弹和平移缩放效果"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
代码实现
这里我写把效果分开来写,最后再合并
平移、缩放
mLayout.java
import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.FrameLayout;import android.widget.Scroller;/** * Created by ChenZehao * on 2019/8/4 */public class mLayout extends FrameLayout{ // 属性变量 private float translationX; // 移动X private float translationY; // 移动Y private float scale = 1; // 伸缩比例 // 移动过程中临时变量 private float actionX; private float actionY; private float spacing; private int moveType; // 0=未选择,1=拖动,2=缩放 private float firstX; private float firstY; public mLayout(Context context) { this(context, null); } public mLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public mLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: moveType = 1; actionX = event.getRawX(); actionY = event.getRawY(); firstX = actionX; firstY = actionY; break; case MotionEvent.ACTION_POINTER_DOWN: moveType = 2; spacing = getSpacing(event); break; case MotionEvent.ACTION_MOVE: if (moveType == 1) { translationX = translationX + event.getRawX() - actionX; translationY = translationY + event.getRawY() - actionY; System.out.println(); setTranslationX(translationX); setTranslationY(translationY); actionX = event.getRawX(); actionY = event.getRawY(); } else if (moveType == 2) { scale = scale * getSpacing(event) / spacing; if(scale >= 1){ setScaleX(scale); setScaleY(scale); }else{ scale = 1; } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: moveType = 0; break; } return true; } // 触碰两点间距离 private float getSpacing(MotionEvent event) { //通过三角函数得到两点间的距离 float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); }}
橡皮筋回弹
import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.FrameLayout;import android.widget.Scroller;/** * Created by ChenZehao * on 2019/8/4 */public class mLayout extends FrameLayout{ //系数可自己更改 private static final float DEFAULT_FATOR = 0.4f; /** * 阻尼因子 */ private float mFator = DEFAULT_FATOR; private Scroller mScroller; /** * 记录上一次触摸事件 */ private MotionEvent mLastMotionEvent; public mLayout(Context context) { this(context, null); } public mLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public mLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(context); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastMotionEvent = MotionEvent.obtain(event); break; case MotionEvent.ACTION_MOVE: int dx = (int) (event.getRawX() - mLastMotionEvent.getRawX()); int dy = (int) (event.getRawY() - mLastMotionEvent.getRawY()); //如果不想对四个方向增加阻尼效果,直接删除即可 //向上平移 if ((Math.abs(dx) < Math.abs(dy)) && dy < 0){ smoothScrollBy(0, -(int) (dy * mFator)); } //向下平移 else if (Math.abs(dx) < Math.abs(dy) && dy > 0) { smoothScrollBy(0, -(int) (dy * mFator)); } //向左平移 else if (Math.abs(dx) > Math.abs(dy) && dx < 0){ smoothScrollBy(-(int) (dx * mFator), 0); } //向右平移 else if (Math.abs(dx) > Math.abs(dy) && dx > 0){ smoothScrollBy(-(int) (dx * mFator), 0); } mLastMotionEvent = MotionEvent.obtain(event); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: smoothScrollTo(0, 0); break; } return true; } private void smoothScrollBy(int dx, int dy) { mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); invalidate(); } private void smoothScrollTo(int fx, int fy) { int dx = fx - mScroller.getFinalX(); int dy = fx - mScroller.getFinalY(); smoothScrollBy(dx, dy); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } super.computeScroll(); }}
平移、缩放、阻尼效果合并
import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.FrameLayout;import android.widget.Scroller;/** * Created by ChenZehao * on 2019/8/4 */public class mLayout extends FrameLayout{ private float scale = 1; // 伸缩比例 // 移动过程中临时变量 private float actionX; private float actionY; private float spacing; private int moveType; // 0=未选择,1=拖动,2=缩放 private float firstX; private float firstY; //系数可自己更改 private static final float DEFAULT_FATOR = 0.4f; /** * 阻尼因子 */ private float mFator = DEFAULT_FATOR; private Scroller mScroller; /** * 记录上一次触摸事件 */ private MotionEvent mLastMotionEvent; public mLayout(Context context) { this(context, null); } public mLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public mLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(context); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mLastMotionEvent = MotionEvent.obtain(event); moveType = 1; actionX = event.getRawX(); actionY = event.getRawY(); firstX = actionX; firstY = actionY; break; case MotionEvent.ACTION_POINTER_DOWN: moveType = 2; spacing = getSpacing(event); break; case MotionEvent.ACTION_MOVE: if (moveType == 1) { int dx = (int) (event.getRawX() - mLastMotionEvent.getRawX()); int dy = (int) (event.getRawY() - mLastMotionEvent.getRawY()); //如果不想对四个方向增加阻尼效果,直接删除即可 //向上平移 if ((Math.abs(dx) < Math.abs(dy)) && dy < 0){ smoothScrollBy(0, -(int) (dy * mFator)); } //向下平移 else if (Math.abs(dx) < Math.abs(dy) && dy > 0) { smoothScrollBy(0, -(int) (dy * mFator)); } //向左平移 else if (Math.abs(dx) > Math.abs(dy) && dx < 0){ smoothScrollBy(-(int) (dx * mFator), 0); } //向右平移 else if (Math.abs(dx) > Math.abs(dy) && dx > 0){ smoothScrollBy(-(int) (dx * mFator), 0); } mLastMotionEvent = MotionEvent.obtain(event); } else if (moveType == 2) { scale = scale * getSpacing(event) / spacing; if(scale >= 1){ setScaleX(scale); setScaleY(scale); }else{ scale = 1; } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_CANCEL: moveType = 0; if(scale == 1) smoothScrollTo(0, 0); break; } return true; } private void smoothScrollBy(int dx, int dy) { mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); invalidate(); } private void smoothScrollTo(int fx, int fy) { int dx = fx - mScroller.getFinalX(); int dy = fx - mScroller.getFinalY(); smoothScrollBy(dx, dy); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } super.computeScroll(); } // 触碰两点间距离 private float getSpacing(MotionEvent event) { //通过三角函数得到两点间的距离 float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); }}
使用方法
在xml文件中添加mLayout布局,便可对mLayout里面的控件和布局进行平移、缩放、阻尼效果的操作
功能扩展——在布局中添加button
如果我们在mLayout布局中添加button,那么会出现获取焦点冲突的问题,导致触摸到按钮时无法进行平移等操作,因此我们需要重写button的dispatchTouchEvent函数,因此要创建一个类mButton来继承Button
点击时事件被button获取,因此要将事件通过dispatchTouchEvent回传给父view,再调用父view的onInterceptTouchEvent函数对拦截到的事件进行处理。
代码如下:
mButton.java
import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;public class mButton extends android.support.v7.widget.AppCompatButton { public mButton(Context context) { super(context); } public mButton(Context context, AttributeSet attrs) { super(context, attrs); } public mButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: getParent().requestDisallowInterceptTouchEvent(false); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: break; } return super.dispatchTouchEvent(ev); }}
mLayout.java
import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.FrameLayout;import android.widget.Scroller;/** * Created by ChenZehao * on 2019/8/4 */public class mLayout extends FrameLayout{ private float scale = 1; // 伸缩比例 // 移动过程中临时变量 private float actionX; private float actionY; private float spacing; private int moveType; // 0=未选择,1=拖动,2=缩放 private float firstX; private float firstY; //系数可自己更改 private static final float DEFAULT_FATOR = 0.4f; /** * 阻尼因子 */ private float mFator = DEFAULT_FATOR; private Scroller mScroller; /** * 记录上一次触摸事件 */ private MotionEvent mLastMotionEvent; public mLayout(Context context) { this(context, null); } public mLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public mLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(context); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mLastMotionEvent = MotionEvent.obtain(event); moveType = 1; actionX = event.getRawX(); actionY = event.getRawY(); firstX = actionX; firstY = actionY; break; case MotionEvent.ACTION_POINTER_DOWN: moveType = 2; spacing = getSpacing(event); break; case MotionEvent.ACTION_MOVE: if (moveType == 1) { int dx = (int) (event.getRawX() - mLastMotionEvent.getRawX()); int dy = (int) (event.getRawY() - mLastMotionEvent.getRawY()); //如果不想对四个方向增加阻尼效果,直接删除即可 //向上平移 if ((Math.abs(dx) < Math.abs(dy)) && dy < 0){ smoothScrollBy(0, -(int) (dy * mFator)); } //向下平移 else if (Math.abs(dx) < Math.abs(dy) && dy > 0) { smoothScrollBy(0, -(int) (dy * mFator)); } //向左平移 else if (Math.abs(dx) > Math.abs(dy) && dx < 0){ smoothScrollBy(-(int) (dx * mFator), 0); } //向右平移 else if (Math.abs(dx) > Math.abs(dy) && dx > 0){ smoothScrollBy(-(int) (dx * mFator), 0); } mLastMotionEvent = MotionEvent.obtain(event); } else if (moveType == 2) { scale = scale * getSpacing(event) / spacing; if(scale >= 1){ setScaleX(scale); setScaleY(scale); }else{ scale = 1; } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_CANCEL: moveType = 0; if(scale == 1) smoothScrollTo(0, 0); break; } return true; } //拦截子button的事件 @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK){ case MotionEvent.ACTION_DOWN: mLastMotionEvent = MotionEvent.obtain(event); moveType = 1; actionX = event.getRawX(); actionY = event.getRawY(); firstX = actionX; firstY = actionY; break; case MotionEvent.ACTION_POINTER_DOWN: moveType = 2; spacing = getSpacing(event); break; case MotionEvent.ACTION_MOVE: if (moveType == 1) { int dx = (int) (event.getRawX() - mLastMotionEvent.getRawX()); int dy = (int) (event.getRawY() - mLastMotionEvent.getRawY()); //如果不想对四个方向增加阻尼效果,直接删除即可 //向上平移 if ((Math.abs(dx) < Math.abs(dy)) && dy < 0){ smoothScrollBy(0, -(int) (dy * mFator)); } //向下平移 else if (Math.abs(dx) < Math.abs(dy) && dy > 0) { smoothScrollBy(0, -(int) (dy * mFator)); } //向左平移 else if (Math.abs(dx) > Math.abs(dy) && dx < 0){ smoothScrollBy(-(int) (dx * mFator), 0); } //向右平移 else if (Math.abs(dx) > Math.abs(dy) && dx > 0){ smoothScrollBy(-(int) (dx * mFator), 0); } mLastMotionEvent = MotionEvent.obtain(event); } else if (moveType == 2) { scale = scale * getSpacing(event) / spacing; if(scale >= 1){ setScaleX(scale); setScaleY(scale); }else{ scale = 1; } } break; case MotionEvent.ACTION_UP: moveType = 0; if(scale == 1) smoothScrollTo(0, 0); if(firstX != event.getRawX() || firstY != event.getRawY()) return true; break; case MotionEvent.ACTION_POINTER_UP: moveType = 0; if(scale == 1) smoothScrollTo(0, 0); break; case MotionEvent.ACTION_CANCEL: moveType = 0; if(scale == 1) smoothScrollTo(0, 0); break; } return super.onInterceptTouchEvent(event); } private void smoothScrollBy(int dx, int dy) { mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); invalidate(); } private void smoothScrollTo(int fx, int fy) { int dx = fx - mScroller.getFinalX(); int dy = fx - mScroller.getFinalY(); smoothScrollBy(dx, dy); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } super.computeScroll(); } // 触碰两点间距离 private float getSpacing(MotionEvent event) { //通过三角函数得到两点间的距离 float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); }}
到此,关于"Android怎么实现橡皮筋回弹和平移缩放效果"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!
平移
效果
阻尼
事件
橡皮
橡皮筋
函数
移动
变量
布局
方向
学习
三角函数
因子
比例
系数
过程
间距
三角
上一
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
如何使用数据库查找某个区域
vs读取db数据库
校园网络安全教育心得
修改mysql数据库路径
云服务器正常使用
河北现代化软件开发密度
网络技术工作室要交税吗
什么软件开发架构的安全性高
软件开发工具四个特性
网络安全求职简历模板
软件开发业务流程图模板
广东crm软件开发外包
ftp服务器更改用户
大数据列式数据库
软件开发业的会计处理
2010数据库引下载
法制宣传网络安全法
大学生网络安全防护
数据库中商品编号用什么类型
政府单位网络安全制度
网络安全主要问题薄弱环节
长沙服务器机柜价格怎么样
数据库安全管理技巧
腾讯网络安全治理
基于框架软件开发实训
y数据库采血
软件开发自学能学会吗
关于数据库数据丢失的说明
没有服务器可以备案吗
软件开发中的基建