看到GitHub上的一个组件:仿58同城的加载动画
实现的效果
如下:
将其作为属性动画的一个练习,以下是我的9块9包邮作品。
思路:
分解这个动画,可以把它分成下落动画,上升动画,旋转动画,底部阴影的拉伸动画,阴影的压缩动画,在下落动画结束后还会变换图标的样式。根据这个思路:
布局文件
:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.chan.like58loadanimation.MainActivity">
<ImageView
android:layout_centerHorizontal="true"
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
android:layout_below="@id/iv"
android:background="#cdcdcd"
android:id="@+id/view"
android:alpha="0.7"
android:layout_marginTop="80dp"
android:layout_centerHorizontal="true"
android:layout_width="20dp"
android:layout_height="5dp"/>
<TextView
android:layout_margin="10dp"
android:id="@+id/tv"
android:text="加载ing"
android:layout_below="@id/view"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
主要代码:
MainActivity:
package com.chan.like58loadanimation;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private ImageView iv;
private View view;
// 保存图片id的数组,这里使用了drawable图片
private int[] img = new int[]{R.drawable.circle, R.drawable.triangle,
R.drawable.square};
private int curImg = 0; // 记录当前使用的图片
private AnimatorSet downShadowSet;
private AnimatorSet upShadowSet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setDropAnimation();
setDownShadowAnimation();
setRotateAnimation();
setUpShadowAnimation();
}
private void initView() {
iv = (ImageView) findViewById(R.id.iv);
view = findViewById(R.id.view);
}
/**
* 设置下落的动画,包括下落和上升
*/
private void setDropAnimation() {
final ObjectAnimator downAnimator = ObjectAnimator.ofFloat(iv,
"translationY", 0, 150);
ObjectAnimator upAnimator = ObjectAnimator.ofFloat(iv, "translationY",
150, 0);
final AnimatorSet set = new AnimatorSet();
set.playSequentially(downAnimator, upAnimator);
set.setDuration(500);
// 通过设置差值器设置动画的效果,根据自己的需要调节
// set.setInterpolator (new AccelerateInterpolator (1.2f));
set.setTarget(iv);
set.start();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
set.start();// 结束一次后循环播放动画
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
downAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// 下落开始同时开启阴影变大的动画
downShadowSet.start();
}
@Override
public void onAnimationEnd(Animator animation) {
// 下落结束切换图片,数组循环是小学数学,不要问我!~我也是问别人的,/(ㄒoㄒ)/~~
curImg++;
iv.setImageResource(img[curImg % img.length]);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
upAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// 上升开始同时开启阴影变小的动画
upShadowSet.start();
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
/**
* 设置旋转动画
*/
private void setRotateAnimation() {
ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(iv, "rotation",
0, 90);
rotateAnimator.setRepeatCount(ValueAnimator.INFINITE);
rotateAnimator.setRepeatMode(ValueAnimator.RESTART);
rotateAnimator.start();
}
/**
* 设置下落时的阴影动画
*/
private void setDownShadowAnimation() {
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(view, "scaleX",
1f, 2f);
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(view, "scaleY",
1.2f);
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha",
0.5f, 1.5f);
downShadowSet = new AnimatorSet();
downShadowSet.playTogether(scaleXAnimator, scaleYAnimator,
alphaAnimator);
downShadowSet.setDuration(500);
downShadowSet.start();
}
/**
* 设置上升时的阴影动画
*/
private void setUpShadowAnimation() {
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(view, "scaleX",
2f, 1f);
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(view, "scaleY",
0.8f);
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(view, "alpha",
1.5f, 0.5f);
upShadowSet = new AnimatorSet();
upShadowSet.playTogether(scaleXAnimator, scaleYAnimator, alphaAnimator);
upShadowSet.setDuration(500);
upShadowSet.start();
}
}
买家秀
下面的阴影简单用了个View,也可以自己绘制或者用图片.
其他:
1-这个例子只是作为属性动画的练习,所以将所有动画都写在MainActivity里,推荐参考GitHub的源码将其写成一个自定义组件方便以后使用(点击传送门进入).
2-其间控制图片下落速度用到了Interpolator差值器,相当于控制动画的加速度。另外动画可以使用view.animate().xxx()形式方便的编写,关于这个以及属性动画的其他参考:
传送门:郭霖-Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法