当前位置: 首页 > news >正文

Android动画实现控件形状、大小逐渐过渡

目录

一个小问题

动画实现


一个很简单的例子,现在有一个提示,需求是在下滑到它触顶时,让其去掉圆角,宽度占满

像这样子

一个小问题

这个提示的实现很简单,我们或许会想到线性布局,大概像下面这样子

但是这时候需要考虑一个问题,如果你的app支持多语言,会不会出现这种情况。

推送受限提示文字太长直接把后面的内容都挤出去了,如果你确定没问题,那线性布局确实会得到更好的性能,不然就要使用约束布局了。

效果如下

说完这个小问题,接下来进入正题

动画实现

只是做演示用,所以偷懒放在onResume了,使用一个定时器来回调用动画

public static int dp2px(float dp) {return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
}
@Override
protected void onResume() {super.onResume();ConstraintLayout clPushTips = findViewById(R.id.cl_push_tips);  //推送修复提示的布局ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams)clPushTips.getLayoutParams(); //推送修复提示的布局参数int total_margin_dp = 20;  //在顶部时左右margin 20dpint total_margin_px = dp2px(total_margin_dp);int total_radius_dp = 50;  //在顶部时圆角 50dpint total_radius_px = dp2px(total_radius_dp);//其中两个参数为初始值和最后动画结束变成的值,传了圆角角度px//动画,最终圆角消失,左右margin设置0ValueAnimator animator_toRectangle = ValueAnimator.ofInt(total_radius_px, 0);  //动画,最终圆角50dp,左右margin设置20dpValueAnimator animator_toRadius = ValueAnimator.ofInt(0, total_radius_px);     animator_toRadius.setDuration(300);   //动画时间300msanimator_toRectangle.setDuration(300);//动画插值器 (作用是决定如何在动画时间内,将传入的初始值参数 过渡到结束值参数)  //有许多种,可以百度 ValueAnimator.setInterpolator//例如初始值100,结束值0  插值器决定是100 90 80...  或者100 90 70 40...animator_toRadius.setInterpolator(new AccelerateInterpolator());  animator_toRectangle.setInterpolator(new AccelerateInterpolator()); ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {  //动画更新监听器GradientDrawable drawable = (GradientDrawable) getResources().getDrawable(R.drawable.shape_ffe1b9_bg_r50dp); //背景图片@Overridepublic void onAnimationUpdate(@NonNull ValueAnimator animation) {int radius_px = (int) animation.getAnimatedValue();  //本次动画更新,圆角角度px//当前对应margin的px值  //例如圆角从100-0  margin从40-0  那如果此次回调的圆角是50,那margin按比例是20 //(40*50/100)int cur_margin_px = total_margin_px * radius_px / total_radius_px;  Log.d("123","onAnimationUpdate 当前圆角px= " + radius_px + "  当前margin_px= " + cur_margin_px);//根据动画进度值,设置过渡布局的背景圆角drawable.setCornerRadius(radius_px);clPushTips.setBackground(drawable);//根据动画进度值设置左右marginlp.setMarginStart(cur_margin_px);lp.setMarginEnd(cur_margin_px);clPushTips.setLayoutParams(lp);}};animator_toRadius.addUpdateListener(animatorUpdateListener); //添加动画更新监听器animator_toRectangle.addUpdateListener(animatorUpdateListener);new CountDownTimer(10000,1000) {  //10s定时器,每秒调一次动画boolean tag = false;@Overridepublic void onTick(long millisUntilFinished) {if(tag){animator_toRadius.start();}else{animator_toRectangle.start();}tag = !tag;}@Overridepublic void onFinish() {}}.start();   }

效果如下

看一下log,现在应该对这个过程有所了解了,其实就是给初始值和结束值,然后按你需要,在一定时间内,通过某种趋势将初始值变到结束值,其中每一次变化都会调用一次onAnimationUpdate,在这个函数里面你使用此值做ui上的变化。

同时在这里我有一点要提醒一下,经过测试,如果手机性能较弱,同样从100-0,onAnimationUpdate调用次数会有差距,比较明显,会造成卡顿,相当于动画时间内能有几帧。

这个次数会受你动画时间长短影响和每次更新ui的工作量影响。例如你200ms,可能调6次,400ms可能是15次、20次,你如果在更新时进行setLayoutParams操作,和你设置背景图片的圆角比起来也会差很多。

说实话不太好用,感觉手机性能弱一些,就很容易卡顿。

在框框一顿操作之后,我还是选择用了其他方式模拟了动画效果,因为会卡,在修复提示的布局下,添加一个布局,颜色和它背景色一样,通过让它长度在MATCH_PARENT和WRAP_CONTENT间切换,实现类似动画效果

    <!--可以拉伸的背景,置于推送修复提示下面,长的时候宽度满屏,让推送修复提示左右的空间被填充, 短的时候隐藏在推送修复提示之下,推送修复提示左右的空间又显示出来--><LinearLayoutandroid:id="@+id/ll_push_tips"android:layout_width="wrap_content"android:layout_height="0dp"android:background="#FFE1B9"android:gravity="center_vertical"android:orientation="horizontal"app:layout_constraintBottom_toBottomOf="@+id/cl_push_tips"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="@+id/cl_push_tips"></LinearLayout>

这样子修复提示不动,只是让底下的一个布局变长度,流畅度会好很多,底下的布局高度和这个修复提示相同。

效果如下

先这样子,后续再看看有没有什么其他方法不卡的。

http://www.lryc.cn/news/608400.html

相关文章:

  • Agentic RAG:自主检索增强生成的范式演进与技术突破
  • Waterfox水狐浏览器、火狐浏览器外观修改
  • XGBoost三部曲:XGBoost参数详解
  • Store / Slice / Reducer
  • 利用DeepSeek将Rust程序的缓冲输出改写为C语言实现提高输出效率
  • Python爬虫实战:研究SimpleCV技术,构建图像获取及处理系统
  • vulnhub-ELECTRICAL靶场攻略
  • 基于OAuth2与JWT的微服务API安全实战经验分享
  • AbstractExecutorService:Java并发核心模板解析
  • Batch Normalization(BN):深度学习中的“训练加速器”与实践指南
  • Vue 详情模块 3
  • 洛谷 P3372 【模板】线段树 1-普及+/提高
  • 星际漫游闪耀2025LEC全球授权展,三大IP与文旅AI打印机共绘国潮宇宙新篇章
  • 【走遍美国精讲笔记】第 1 课:林登大街 46 号
  • 深入 Go 底层原理(一):Slice 的实现剖析
  • 波士顿咨询校招面试轮次及应对策略解析
  • PYTHON从入门到实践-18Django从零开始构建Web应用
  • 二叉搜索树(C++实现)
  • 蓝桥杯----串口
  • [硬件电路-120]:模拟电路 - 信号处理电路 - 在信息系统众多不同的场景,“高速”的含义是不尽相同的。
  • MyBatis与MySQL
  • 驾驶场景玩手机识别:陌讯行为特征融合算法误检率↓76% 实战解析
  • 综合:单臂路由+三层交换技术+telnet配置+DHCP
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年8月2日第154弹
  • 位菜:仪式锚与价值符
  • 先学Python还是c++?
  • Mybatis学习之各种查询功能(五)
  • Web 开发 10
  • stm32F407 实现有感BLDC 六步换相 cubemx配置及源代码(二)
  • sqli-labs:Less-20关卡详细解析