Android怎么实现橡皮筋回弹和平移缩放效果
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章主要介绍"Android怎么实现橡皮筋回弹和平移缩放效果",在日常操作中,相信很多人在Android怎么实现橡皮筋回弹和平移缩放效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法
千家信息网最后更新 2026年11月03日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安全错误
数据库的锁怎样保障安全
保险科技 互联网保险
科技赋能下的互联网金融
科技和互联网公司
互联网科技有限公司图片
互联网科技战争
北京互联网络科技有限公司
狮子座互联网科技有限公司
壕鑫互联网络科技
深圳市运趣互联网科技有限公司
互联网教育科技公司vipkid
常德市电业局互联网科技部
阿里互联网科技公司
南山科技园互联网公司有哪些
互联网科技大奖都有哪些公司
互联网科技人工智能实验室
河南住房之家互联网科技
美国互联网科技实力
互联网领先科技活动
银川新华互联网科技学校原画
互联网大会出现的黑科技
南京欣网互联网络科技有限公司
鸠鸠互联网科技
互联网与新科技
苏州大垚互联网科技
深圳国际航运科技和互联网
996高科技互联网公司
同城互联网络科技
青岛易易互联网科技
青岛互联网科技园
优雇互联网科技有限公司