目录
本节内容:
简单的使用:
1、补间动画
2、属性动画
android的有两大动画类型:
1、View Animation,包括补间动画和帧动画
不修改属性值,作用在控件上的显示效果。
2、Property Animator属性动画,包括ValueAnimator和ObjectAnimation;通过修改属性值来达到动画的改变。
一、View动画使用:
1.1、补间动画
1.1.1、xml方式
1、
2、输入文件名、选好下图选项即可
创建文件成功
咱们写个缩放动画:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0"
android:toXScale="2"
android:fromYScale="0"
android:toYScale="2"
android:pivotX="50%"
android:pivotY="50%"
android:duration ="1000"
android:interpolator = "@android:anim/anticipate_interpolator"
>
</scale>
为控件添加view动画并监听:
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.myanimation)
findViewById<Button>(R.id.btn).startAnimation(loadAnimation)
loadAnimation.setAnimationListener(object : Animation.AnimationListener{
override fun onAnimationRepeat(animation: Animation?) {
Log.i(TAG,"动画重复执行")
}
override fun onAnimationEnd(animation: Animation?) {
Log.i(TAG,"动画结束")
}
override fun onAnimationStart(animation: Animation?) {
Log.i(TAG,"动画开始")
}
})
}
}
2020-04-05 19:58:55.359 5388-5388/com.example.animation I/Animation: 动画开始
2020-04-05 19:58:56.110 5388-5388/com.example.animation I/Animation: 动画结束
挺好用的,动画属性:
android:fromXScale //开始时相对自身的缩放比 float 1.0表示和原来一样大
android:toXScale //结束时相对于自身的缩放比 float
Y同理oa
android:pivotX //动画开始起点x轴坐标 float/百分数/百分数p,为数值时以控件左上角取相对位置,为百分数以控件左上角取相对位置,
在控件中间就可以用50%表示,为百分数p时以父控件左上角取相对位置
Y同理
android:duration //动画持续时间
android:fillAfter //是否保持动画最后状态
android:fillBefore // 同理
android:repeatCount //重复次数
android:repeatMode //重复类型 倒叙:reverse 重来:restart
android:interpolator //插值器
//各种插值器:
@android:anim/anticipate_interpolator//撤步加速跑,
@android:anim/accelerate_decelerate_interpolator//中间快两头慢
@android:anim/accelerate_interpolator//先慢后快,线性加速
@android:anim/anticipate_overshoot_interpolator//开始的时候向后然后向前甩一定值后返回最后的值
@android:anim/decelerate_interpolator//减速
@android:anim/bounce_interpolator/小球掉落谈起效果
@android:anim/cycle_interpolator//正弦曲线
@android:anim/linear_interpolator//速度不变
@android:anim/overshoot_interpolator//向前甩一定值后再回到原来位置
四种动画类型:
alpha、scale、translate、rotate
1.1.2、代码实现
看构造器:
var scale =ScaleAnimation(0f,1f, 0f, 1f)
scale.duration = 3000
findViewById<Button>(R.id.btn).startAnimation(scale)
1.2帧动画
12张图不贴那么多了
首先需要把图片资源放到drawable文件夹下
并创建一个xml文件:
其中lineclock.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/lc_1" android:duration="100"></item>
<item android:drawable="@drawable/lc_2" android:duration="100"></item>
<item android:drawable="@drawable/lc_3" android:duration="100"></item>
<item android:drawable="@drawable/lc_4" android:duration="100"></item>
<item android:drawable="@drawable/lc_5" android:duration="100"></item>
<item android:drawable="@drawable/lc_6" android:duration="100"></item>
<item android:drawable="@drawable/lc_7" android:duration="100"></item>
<item android:drawable="@drawable/lc_8" android:duration="100"></item>
<item android:drawable="@drawable/lc_9" android:duration="100"></item>
<item android:drawable="@drawable/lc_10" android:duration="100"></item>
<item android:drawable="@drawable/lc_11" android:duration="100"></item>
<item android:drawable="@drawable/lc_12" android:duration="100"></item>
</animation-list>
布局文件:
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/lineclock"
android:background="@color/colorPrimary"
>
</ImageView>
启动帧动画:
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val animationDrawable = findViewById<ImageView>(R.id.iv).drawable as AnimationDrawable
animationDrawable.start()
}
}
1.3属性动画使用
1.3.1、api1:ValueAnimator
产生值用来修改值
1.3.1.1、xml方式
<?xml version="1.0" encoding="utf-8"?>
<animator
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"
android:duration="2000"
android:valueFrom="0"
android:valueTo="300"
android:valueType="intType"
android:repeatCount = "infinite"
android:repeatMode="reverse"
/>
各项属性:
android:duration
android:valueFrom
android:valueTo
android:startOffset
android:repeatCount
android:repeatMode
android:valueType
android:interpolator
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.btn)
//这段代码是监听全局视图树是否绘制完成
//否则获取的宽高很有可能为0
var vto = button.getViewTreeObserver();
var currW = 0
var currH = 0
vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
//移除监听
button.getViewTreeObserver().removeGlobalOnLayoutListener(this);
currW = button.width
currH = button.height
}
});
val scale:ValueAnimator = AnimatorInflater.loadAnimator(this, R.animator.myanimator) as ValueAnimator
scale.addUpdateListener {
var animatedValue:Int = it.animatedValue as Int
button.layout(0, 0, currW+animatedValue, currH+animatedValue)
}
scale.start()
}
}
1.3.1.2、代码实现:
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.btn)
var vto = button.getViewTreeObserver();
var currW = 0
var currH = 0
vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
button.getViewTreeObserver().removeGlobalOnLayoutListener(this);
currW = button.width
currH = button.height
}
});
val scale = ValueAnimator.ofInt(0, 300);
scale.duration = 3000;
scale.addUpdateListener {
val animatedValue = it.animatedValue as Int
button.layout(0, 0, currW+animatedValue, currH+animatedValue)
}
scale.start()
}
}
1.3.1、api2:ObjectAnimator
可以直接作用在控件上
1.3.2.1、xml方式实现
animator/object_translate_x.xml:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="scaleX"
android:duration="3000"
android:valueFrom="1f"
android:valueTo="3f"
android:valueType="floatType"
android:repeatCount="infinite"
android:repeatMode="reverse"
>
</objectAnimator>
animator/object_translate_y.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="scaleY"
android:duration="3000"
android:valueFrom="1f"
android:valueTo="3f"
android:valueType="floatType"
android:repeatCount="infinite"
android:repeatMode="reverse"
>
</objectAnimator>
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.btn)
var vto = button.getViewTreeObserver();
val scaleY = AnimatorInflater.loadAnimator(this, R.animator.object_translate_y)
val scaleX = AnimatorInflater.loadAnimator(this, R.animator.object_translate_x)
scaleX.setTarget(button)
scaleY.setTarget(button)
scaleY.start()
scaleX.start()
}
}
1.3.2.2、代码实现
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.btn)
var vto = button.getViewTreeObserver();
val scaleY = ObjectAnimator.ofFloat(button, "scaleY", 1f, 3f)
val scaleX = ObjectAnimator.ofFloat(button, "scaleX", 1f, 3f)
scaleY.duration = 3000;
scaleY.repeatCount = -1
scaleY.repeatMode = ObjectAnimator.REVERSE
scaleX.duration = 3000;
scaleX.repeatCount = -1
scaleX.repeatMode = ObjectAnimator.REVERSE
scaleY.start()
scaleX.start()
}
}
效果:
1.3.2.2.1、Path路径动画
我们发现,有两个重载方法还有Path作参数的,这个怎么用呢?又有什么效果呢?下边来看看吧:
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val Iv = findViewById<ImageView>(R.id.iv)
val path = Path();
path.moveTo(0f,0f);
path.lineTo(100f,100f);
path.lineTo(0f,100f);
path.lineTo(0f,0f);
val objectAnimator = ObjectAnimator.ofFloat(Iv, "translationX","translationY",path );
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(LinearInterpolator());
objectAnimator.start();
}
}
1.3.2.2.2、ofPropertyValuesHolder
我们查看注释说明:
- 该类保存有关属性及其值的信息
- 在动画中播放。PropertyValuesHolder对象可用于创建
- 动画与ValueAnimator或ObjectAnimator操作几个不同的属性时可并行。
其实我们之前属性动画中用的ofInt,ofFolat创建的动画最终都会放到PropertyValuesHolder里,不信你看:
public static ValueAnimator ofInt(int... values) {
ValueAnimator anim = new ValueAnimator();
anim.setIntValues(values);
return anim;
}
第三行anim.setIntValues(values);
public void setIntValues(int... values) {
if (values == null || values.length == 0) {
return;
}
if (mValues == null || mValues.length == 0) {
setValues(PropertyValuesHolder.ofInt("", values));
} else {
PropertyValuesHolder valuesHolder = mValues[0];
valuesHolder.setIntValues(values);
}
// New property/values/target should cause re-initialization prior to starting
mInitialized = false;
}
在valuesHolder.setIntValues(values)这句就说明了一切,所以android还会暴露出这个方法给我们用的
ofPropertyValuesHolder()里面要传入参数有
PropertyValuesHolder对象,看看创建实例函数:
public static PropertyValuesHolder ofFloat(String propertyName, float... values)
public static PropertyValuesHolder ofInt(String propertyName, int... values)
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
使用方法:
1、ofFloat():
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val Iv = findViewById<ImageView>(R.id.iv)
ValueAnimator.ofPropertyValuesHolder()
val objectAnimator = ObjectAnimator.ofInt()
val translationX = PropertyValuesHolder.ofFloat("TranslationX", 0f, 100f, 0f, 0f)
val translationY = PropertyValuesHolder.ofFloat("TranslationY", 0f, 100f, 100f, 0f)
val rotation = PropertyValuesHolder.ofFloat("Rotation", 0f, 90f, 180f, 270f, 360f)
val animator=
ObjectAnimator.ofPropertyValuesHolder(Iv, translationX, translationY, rotation)
animator.duration = 3000
animator.repeatCount = -1
animator.start()
}
}
效果: 这个平移动画有点难看出来-_-!
1.3.2.2.3、属性关键帧
ofKeyframe
需要Keyframe对象:
第一个参数:动画进度
第二个参数:动画值
使用:
class MainActivity : AppCompatActivity() {
var TAG = "Animation"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val Iv = findViewById<ImageView>(R.id.iv)
ValueAnimator.ofPropertyValuesHolder()
val frame0 = Keyframe.ofFloat(0f, 0f)
val frame1 = Keyframe.ofFloat(.25f, 45f)
val frame2 = Keyframe.ofFloat(.5f, 90f)
val frame3 = Keyframe.ofFloat(.75f, 45f)
val frame4 = Keyframe.ofFloat(1f, 0f)
val holder =
PropertyValuesHolder.ofKeyframe("Rotation", frame0, frame1, frame2, frame3, frame4)
val animator = ObjectAnimator.ofPropertyValuesHolder(Iv, holder)
animator.duration = 3000
animator.repeatCount = -1
animator.start()
}
}
到这我还没讲任何关于插值器啊,估值器啊,ofObject()啊什么的,下篇吧。
下篇
https://blog.csdn.net/weixin_43860530/article/details/105346998