属性动画的核心方法: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>
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>
(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 }
作者:听着music睡
出处:http://www.cnblogs.com/xqxacm/
Android交流群:38197636
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。