当前位置: 首页 > 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.dtcms.com/a/311864.html

相关文章:

  • 智能制造——解读CMMM评估手册【附全文阅读】
  • DyWA:用于可推广的非抓握操作的动态自适应世界动作模型
  • 硅基计划3.0 学习总结 伍 优先级队列排序初识
  • 【Vue3】Class绑定:从基础到高级的完整指南
  • Web前端实现银河粒子流动特效的3种技术方案对比与实践
  • 【完结篇】华为OpenStack架构学习9篇 连载—— 09 OpenStack编排管理【附全文阅读】
  • 深入 Go 底层原理(三):Goroutine 的调度策略
  • OSPF综合
  • VS Code高效开发指南:快捷键与配置优化详解
  • 深入 Go 底层原理(十二):map 的实现与哈希冲突
  • Mybatis学习之获取参数值(四)
  • 字符串(java不死)
  • c++之基础B(进制转换)(第三课)
  • 详解Python标准库之并发执行
  • AI Agent开发学习系列 - LangGraph(3): 有多个输入的Graph
  • C#多数据库批量执行脚本工具
  • OneCode3.0 核心表达式技术深度剖析:从架构设计到动态扩展
  • 波士顿咨询校招面试轮次及应对策略解析
  • 双机并联无功环流抑制虚拟阻抗VSG控制【simulink仿真模型实现】
  • OneCodeServer 架构深度解析:从组件设计到运行时机制
  • 「iOS」————weak底层原理
  • Conda创建虚拟环境,解决不同项目的冲突!
  • Windows本地使用dify搭建知识库+ollama+deepseek
  • 从零打造大语言模型--处理文本数据
  • vue引入阿里巴巴矢量图库的方式
  • SpringBoot3.x入门到精通系列: 2.3 Web开发基础
  • sifu mod制作 相关经验
  • 11:java学习笔记:1D array(1维数组)
  • Windows下定位Mingw编译的Qt程序崩溃堆栈
  • Python科研数据可视化技术