该方法的实现目的:以整形初始值平稳过渡到整形结束值。
比如 ValueAnimator.ofInt(0,100) , 实现的即数值从0平稳的变化到100
比如实现如下一个效果:
改变控件的样式,圆形和圆角长方形切换
实现思路很简单,即高度不变,改变控件的宽度(圆形时:宽高相等,长方形时:宽度为屏幕宽度-两边边距),顺便设置一个背景值,动画执行过程随便设个值(例子250毫秒)
现在看具体实现:
1、首先布局文件,设置两个按钮和一个效果控件 , 这里设置执行效果控件的高度固定为50dp,当然可以自行扩展
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:orientation="vertical"
8 android:gravity="center"
9 tools:context=".MainActivity">
10
11 <TextView
12 android:id="@+id/tvToCir"
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content"
15 android:gravity="center"
16 android:text="长方形变圆形"
17 android:padding="10dp"
18 ></TextView>
19
20
21 <TextView
22 android:id="@+id/tvToRect"
23 android:layout_width="wrap_content"
24 android:layout_height="wrap_content"
25 android:gravity="center"
26 android:text="圆形变长方形"
27 android:padding="10dp"
28 android:layout_marginTop="20dp"
29 ></TextView>
30
31
32 <TextView
33 android:id="@+id/tvAdd"
34 android:layout_width="match_parent"
35 android:layout_height="50dp"
36 android:text="+"
37 android:gravity="center"
38 android:textColor="#fff"
39 android:background="@drawable/shape_main_add_rect"
40 app:layout_constraintRight_toRightOf="parent"
41 android:layout_marginRight="30dp"
42 android:layout_marginLeft="30dp"
43 android:layout_marginTop="30dp"
44 app:layout_constraintBottom_toBottomOf="parent"
45 android:layout_marginBottom="30dp"
46 />
47
48 </LinearLayout> xml布局文件2、分别写下长方形和圆形状态时对应的背景文件,即drawable类型的shape属性
(1)圆形,圆角为25dp(因为宽度为50dp,设置一半数值即为圆形效果), 背景绿色,再加一个白色的边,为了效果好看些
1 <?xml version="1.0" encoding="utf-8"?>
2 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3 <!--第一层阴影-->
4 <item>
5 <shape android:shape="rectangle">
6 <solid android:color="#0F000000" />
7 <corners android:radius="25dp" />
8 </shape>
9 </item>
10 <item
11 android:bottom="2dp"
12 android:left="2dp"
13 android:right="2dp"
14 android:top="2dp">
15 <shape android:shape="rectangle">
16 <solid android:color="#fff" />
17 <corners android:radius="25dp" />
18 </shape>
19 </item>
20 <!--第二层前景-->
21 <item
22 android:bottom="5dp"
23 android:left="5dp"
24 android:right="5dp"
25 android:top="5dp">
26 <shape android:shape="rectangle">
27 <solid android:color="#29C66A"/>
28 <corners android:radius="25dp" />
29 </shape>
30 </item>
31
32 </layer-list> shape_main_add_cir.xml(2)长方形,同上,不过圆角设置可以设置小一点,这个读者可以仿着圆角自己写一个,完整代码请到最后查看
3、动画的实现方法,以长方形到圆形为例,只需依赖ValueAnimator.ofInt()方法设置数值从25dp到屏幕宽度-两边边距即可
1 // 长方形变圆形
2 public void rectToCir(){
3 // 异常,如果动画对象为null 或者 动画在执行中
4 if (valAnimator!=null && valAnimator.isRunning()){
5 return;
6 }
7 // 长方形宽度为屏幕宽度-去两边各30dp, 圆形宽度为50dp, 因为设置的空间高度为50dp,圆角为25dp,即实现了圆形图标
8 // ofInt(int a, int b)表示 动画取值从a到b
9 valAnimator = ValueAnimator.ofInt(screenWidth-2*dpToPx(30), dpToPx(50));
10 valAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
11 @Override
12 public void onAnimationUpdate(ValueAnimator animation) {
13 // 定义动画的值,即ofInt方法设置的取值范围,值变化时即执行该回调
14 int h = (int) animation.getAnimatedValue();
15 // 结果处理,若值为宽度-2*50dp,说明为长方形,则设置文案
16 if (h==screenWidth-2*dpToPx(30)){
17 tvAdd.setText("");
18 }else if (h==dpToPx(50)){
19 // 说明变圆形了,设置文案 , 同时设置背景
20 tvAdd.setText("+");
21 tvAdd.setTextSize(14);
22 tvAdd.setBackgroundResource(R.drawable.shape_main_add_cir);
23 }
24 LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) tvAdd.getLayoutParams(); //取控件textView当前的布局参数
25 linearParams.width = h;// 控件的高强制设成20
26 tvAdd.setLayoutParams(linearParams);
27
28 }
29 });
30 // 动画执行过程为250毫秒
31 valAnimator.setDuration(250);
32 // 开始执行动画
33 valAnimator.start();
34 } Activity完整代码如下:
1 package com.mxqx.xqxtest;
2
3 import androidx.appcompat.app.AppCompatActivity;
4
5 import android.animation.ValueAnimator;
6 import android.content.res.Resources;
7 import android.os.Bundle;
8 import android.view.View;
9 import android.view.WindowManager;
10 import android.widget.LinearLayout;
11 import android.widget.TextView;
12 /**
13 * @author : https://www.cnblogs.com/xqxacm/ xqx
14 * @create_day : 2021/10/2
15 * @description :
16 */
17 public class MainActivity extends AppCompatActivity {
18
19 TextView tvToCir; // 长方形变圆形按钮
20 TextView tvToRect; // 圆形变长方形按钮
21 TextView tvAdd; // 添加按钮
22 int screenWidth = 0; // 屏幕宽度
23 @Override
24 protected void onCreate(Bundle savedInstanceState) {
25 super.onCreate(savedInstanceState);
26 setContentView(R.layout.activity_main);
27 initView();
28 }
29
30 private void initView() {
31 tvToCir = findViewById(R.id.tvToCir);
32 tvToRect = findViewById(R.id.tvToRect);
33 tvAdd = findViewById(R.id.tvAdd);
34 // 获取屏幕宽度
35 WindowManager wm1 = this.getWindowManager();
36 screenWidth = wm1.getDefaultDisplay().getWidth();
37
38 // 点击事件
39 tvToCir.setOnClickListener(new View.OnClickListener() {
40 @Override
41 public void onClick(View view) {
42 // 长方形变圆形
43 rectToCir();
44 }
45 });
46 tvToRect.setOnClickListener(new View.OnClickListener() {
47 @Override
48 public void onClick(View view) {
49 // 圆形变长方形
50 cirToTri();
51 }
52 });
53 }
54
55 ValueAnimator valAnimator ;
56 // 长方形变圆形
57 public void rectToCir(){
58 // 异常,如果动画对象为null 或者 动画在执行中
59 if (valAnimator!=null && valAnimator.isRunning()){
60 return;
61 }
62 // 长方形宽度为屏幕宽度-去两边各30dp, 圆形宽度为50dp, 因为设置的空间高度为50dp,圆角为25dp,即实现了圆形图标
63 // ofInt(int a, int b)表示 动画取值从a到b
64 valAnimator = ValueAnimator.ofInt(screenWidth-2*dpToPx(30), dpToPx(50));
65 valAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
66 @Override
67 public void onAnimationUpdate(ValueAnimator animation) {
68 // 定义动画的值,即ofInt方法设置的取值范围,值变化时即执行该回调
69 int h = (int) animation.getAnimatedValue();
70 // 结果处理,若值为宽度-2*50dp,说明为长方形,则设置文案
71 if (h==screenWidth-2*dpToPx(30)){
72 tvAdd.setText("");
73 }else if (h==dpToPx(50)){
74 // 说明变圆形了,设置文案 , 同时设置背景
75 tvAdd.setText("+");
76 tvAdd.setTextSize(14);
77 tvAdd.setBackgroundResource(R.drawable.shape_main_add_cir);
78 }
79 LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) tvAdd.getLayoutParams(); //取控件textView当前的布局参数
80 linearParams.width = h;// 控件的高强制设成20
81 tvAdd.setLayoutParams(linearParams);
82
83 }
84 });
85 // 动画执行过程为250毫秒
86 valAnimator.setDuration(250);
87 // 开始执行动画
88 valAnimator.start();
89 }
90 // 圆形变长方形
91 public void cirToTri(){
92 if (valAnimator!=null && valAnimator.isRunning()){
93 return;
94 }
95 valAnimator = ValueAnimator.ofInt(dpToPx(50), screenWidth-2*dpToPx(30));
96 valAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
97 @Override
98 public void onAnimationUpdate(ValueAnimator animation) {
99 int h = (int) animation.getAnimatedValue();
100 if (h==screenWidth-2*dpToPx(30)){
101 tvAdd.setText("添加");
102 tvAdd.setBackgroundResource(R.drawable.shape_main_add_rect);
103 }else if (h==dpToPx(50)){
104 tvAdd.setText("");
105 }
106 LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) tvAdd.getLayoutParams(); //取控件textView当前的布局参数
107 linearParams.width = h;// 控件的高强制设成20
108 tvAdd.setLayoutParams(linearParams);
109
110 }
111 });
112 valAnimator.setDuration(250);
113 valAnimator.start();
114 }
115
116 /**
117 * 把以 dp 为单位的值,转化为以 px 为单位的值
118 *
119 * @param dpValue 以 dp 为单位的值
120 * @return px value
121 */
122 public static int dpToPx(int dpValue) {
123 return (int) (dpValue * DENSITY + 0.5f);
124 }
125 /**
126 * 屏幕密度,系统源码注释不推荐使用
127 */
128 public static final float DENSITY = Resources.getSystem()
129 .getDisplayMetrics().density;
130 } MainActivity.java
|