Android中如何在动画执行时改变View的尺寸?
实现环形进度条+文本的过渡动画(Android Fragment)
我刚在Android Studio的Fragment里搞定了一个从100%平滑过渡到目标值的动画效果,用到了自定义环形进度条和同步更新的文本,把实现过程整理出来给你参考:
1. 自定义环形ProgressBar的Drawable
首先是你用到的环形Drawable文件,我把代码和每个属性的作用拆解一下:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:useLevel="true" android:innerRadiusRatio="2.3" android:shape="ring" android:thickness="8sp" > <solid android:color="@color/colorPrimary" /> </shape>
android:useLevel="true":这个是核心属性,必须开启才能让Shape跟着ProgressBar的进度值动态显示环形长度android:innerRadiusRatio="2.3":控制环形内半径的比例,数值越小内半径越大,2.3的比例会让环形视觉上更协调android:thickness="8sp":设置环形的厚度,用sp单位能适配不同屏幕的文字缩放规则<solid>标签:定义环形的填充色,这里直接用了项目的主题色colorPrimary
2. Fragment中的动画实现逻辑
在Fragment的生命周期方法(比如onViewCreated)里,我们可以通过ValueAnimator实现从100%到目标值的平滑过渡,同时同步更新ProgressBar和TextView:
先看布局中的控件示例
<!-- 环形进度条 --> <ProgressBar android:id="@+id/circular_progress" android:layout_width="120dp" android:layout_height="120dp" style="?android:attr/progressBarStyleHorizontal" android:progressDrawable="@drawable/你的环形Drawable文件名" /> <!-- 进度文本 --> <TextView android:id="@+id/progress_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="100%" android:textSize="18sp" />
Kotlin版本代码
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val circularProgress = view.findViewById<ProgressBar>(R.id.circular_progress) val progressText = view.findViewById<TextView>(R.id.progress_text) val targetProgress = 65 // 替换成你需要的目标数值 // 创建从100到目标值的数值动画 val animator = ValueAnimator.ofInt(100, targetProgress) animator.duration = 1500 // 动画时长,单位毫秒 animator.addUpdateListener { animation -> val currentProgress = animation.animatedValue as Int // 更新进度条 circularProgress.progress = currentProgress // 更新文本 progressText.text = "$currentProgress%" } // 启动动画 animator.start() }
Java版本代码
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ProgressBar circularProgress = view.findViewById(R.id.circular_progress); TextView progressText = view.findViewById(R.id.progress_text); int targetProgress = 65; // 目标进度值 ValueAnimator animator = ValueAnimator.ofInt(100, targetProgress); animator.setDuration(1500); animator.addUpdateListener(animation -> { int currentProgress = (int) animation.getAnimatedValue(); circularProgress.setProgress(currentProgress); progressText.setText(currentProgress + "%"); }); animator.start(); }
额外优化小提示
- 记得给ProgressBar设置
style="?android:attr/progressBarStyleHorizontal",否则自定义的环形Drawable不会生效 - 如果想要动画过渡更自然,可以添加插值器,比如
animator.interpolator = AccelerateDecelerateInterpolator(),让动画先加速后减速 - 目标值如果是动态获取的(比如接口返回),直接把
targetProgress替换成对应变量即可
内容的提问来源于stack exchange,提问作者bleand




