Android手游按钮点击缩放动画异常求助:无过渡且应用卡顿
解决Android按钮缩小动画卡顿&无过渡问题
嘿,作为移动端开发新手,你遇到的这个问题其实非常典型——你在UI主线程里做了阻塞式的循环和睡眠操作,直接导致UI无法实时更新,才会出现“直接跳尺寸”和卡顿的情况。
为什么你的代码会出问题?
Android的所有UI更新操作都必须在主线程(UI线程)执行,但如果主线程被耗时操作(比如你的while循环+SystemClock.sleep(50))占住,系统就没时间去刷新界面。你在循环里多次调用setLayoutParams,这些更新请求会全部被积压,直到整个循环结束才会一次性执行,所以看起来按钮直接跳到了最终的小尺寸,同时主线程被阻塞的这段时间,整个App都会卡顿甚至无响应。
正确的解决方案:用属性动画(ValueAnimator)
Android官方提供了专门的属性动画框架,能帮你在不阻塞主线程的前提下,平滑地完成UI属性的过渡。这里用ValueAnimator来实现按钮从120到2的尺寸变化,完全符合你的需求:
button.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View arg0) { // 创建从120到2的数值动画,对应按钮的宽高变化 ValueAnimator sizeAnimator = ValueAnimator.ofInt(120, 2); // 设置总动画时长:和你原来循环的总时长一致((120-2)*50ms = 5900ms) sizeAnimator.setDuration(5900); // 添加动画更新监听,实时修改按钮尺寸 sizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int currentSize = (int) animation.getAnimatedValue(); ViewGroup.LayoutParams params = button.getLayoutParams(); params.width = currentSize; params.height = currentSize; button.setLayoutParams(params); } }); // 启动动画 sizeAnimator.start(); } });
额外优化:点击后弹出更快的新按钮
如果要实现“点击后弹出缩小更快的新按钮”,你可以给动画添加结束监听,在动画完成后创建新按钮,并给它设置更短的动画时长(让缩小速度更快):
sizeAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { // 动画结束后,创建新按钮 Button newButton = new Button(MainActivity.this); newButton.setText("新按钮"); // 设置新按钮的初始位置和尺寸(比如随机位置) ViewGroup.LayoutParams newParams = new ViewGroup.LayoutParams(120, 120); newButton.setLayoutParams(newParams); // 添加到布局里 ((ViewGroup) arg0.getParent()).addView(newButton); // 给新按钮设置更快的缩小动画(比如把时长改成3000ms,比原来的5900ms快) newButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ValueAnimator fasterAnimator = ValueAnimator.ofInt(120, 2); fasterAnimator.setDuration(3000); fasterAnimator.addUpdateListener(animator -> { int size = (int) animator.getAnimatedValue(); ViewGroup.LayoutParams p = newButton.getLayoutParams(); p.width = size; p.height = size; newButton.setLayoutParams(p); }); fasterAnimator.start(); } }); } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} });
新手必记知识点
永远不要在UI线程里做以下操作:
- 耗时循环/计算
Thread.sleep()或SystemClock.sleep()- 网络请求、文件读写等IO操作
这些操作都会阻塞主线程,导致App卡顿、无响应,甚至被系统判定为ANR(应用无响应)。而属性动画框架已经帮我们处理了后台计算+主线程更新的逻辑,是做UI过渡动画的最优选择。
内容的提问来源于stack exchange,提问作者Konrad Czajkowski
相关产品推荐
相关产品推荐

