看到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的用法