评论

收藏

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

移动开发 移动开发 发布于:2021-10-25 17:04 | 阅读数:301 | 评论:0

该方法的实现目的:以整形初始值平稳过渡到整形结束值。
比如 ValueAnimator.ofInt(0,100) , 实现的即数值从0平稳的变化到100
比如实现如下一个效果:
改变控件的样式,圆形和圆角长方形切换
实现思路很简单,即高度不变,改变控件的宽度(圆形时:宽高相等,长方形时:宽度为屏幕宽度-两边边距),顺便设置一个背景值,动画执行过程随便设个值(例子250毫秒)
DSC0000.gif

现在看具体实现:
1、首先布局文件,设置两个按钮和一个效果控件 , 这里设置执行效果控件的高度固定为50dp,当然可以自行扩展

DSC0001.gif DSC0002.gif
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
关注下面的标签,发现更多相似文章