三叶草 发表于 2021-10-25 17:04:39

属性动画的核心方法:ValueAnimator.ofInt(int... values)

该方法的实现目的:以整形初始值平稳过渡到整形结束值。
比如 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
https://www.cnblogs.com/xqxacm/p/15457512.html
页: [1]
查看完整版本: 属性动画的核心方法:ValueAnimator.ofInt(int... values)