动画已经成立UI设计中一个非常重要的组成部分,在Android 5.X的UI设计Material Design中更是使用了大量的动画效果,同时Google也在官方设计文档上增加了对动画的设计指导。
在Android 5.X中,Material Design大量使用了Ripple效果,即点击后的波纹效果。可以通过如下代码设置波纹背景。
android:background="?android:attr/selectableItemBackground"
android:background="?android:attr/selectableItemBackgroundBorderless"
波纹有边界是指波纹被限制在控件的边界中,而波纹超出边界的则是波纹不会限制在控件边界中,会呈圆形发散出去,下面通过一个实例演示下Android 5.X的波纹效果,XML代码如下所示。
显示效果图如下所示。
同样,你也可以在XML文件中直接创建一个具有Ripple效果的XML文件,代码如下所示。
-
使用犯法如下所示,与使用一般的XML资源方法相同。
显示效果如图所示。
这个动画效果在google IO大会上的演示视频中出现了很多次,具体表现为一个View以圆形的方式展开,揭示出来。通过ViewAnimationUtils.createCircularReveal()方法可以创建一个RevealAnimator动画,代码如下所示。
public static Animator createCircularReveal(View view,
int centerX, int centerY, float startRadius, float endRadius) {
return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
}
RealAnimator的使用非常简单,主要是设置几个关键点的坐标:
通过下面的例子,可以非常直观地感受到这种动画效果,XML代码如下所示。
package test.chenj.study_12;
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.annotation.TargetApi;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
public class CircluarRevealActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_circluar_reveal);
final View oval = findViewById(R.id.oval);
final View rect = findViewById(R.id.rect);
oval.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
Animator animator = ViewAnimationUtils.createCircularReveal(oval,
oval.getWidth()/2,
oval.getHeight()/2,
oval.getWidth(),
0);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.setDuration(2000);
animator.start();
}
});
rect.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
Animator animator = ViewAnimationUtils.createCircularReveal(rect,
0,
0,
0,
(float)Math.hypot(rect.getWidth(),rect.getHeight()));
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(2000);
animator.start();
}
});
}
}
以上程序设置了两种形式,通过设置不同地坐标值,改变圆形展开地方式,如下图所示。
在Android5.X中,系统提供了视图状态改变来设置一个视图地状态切换动画。
StateListAnimator作为视图改变地动画效果,通常会使用Selector来进行设置,但以前设置Selector的时候,通常是修改背景图来达到反馈的效果。现在,在Android5.X中,可以使用动画来作为改变的效果。
在Xml中定义一个StateListAnimator,并添加到Selector中,代码如下所示。
-
-
在一般的XML布局中,使用如下代码将StateListAnimator添加给一个视图。
同样,在代码中也可以调用AnimationInflater.loadStateListAnimator()方法,并且通过View.setStateListAnimator()方法分配动画到视图上。
animated-selector同样是一个状态改变的动画效果Selector。在Android 5.0中,很多Material Design的控件设计类似帧动画的切换效果,懂事通过这种方式来实现的,例如我们熟悉的check_box的动画效果,就是使用类似帧动画的切换效果,模拟进行点击时的切换效果,模拟进行点击时的切换效果,如图所示。
下面就仿照这个例子来实现一个具有动画效果的切换按钮。首先需要一组类似上图的切换图,如图所示。
有了这样一组图,就可以在XML文件中定义animated-selector。animated-selector与selector的使用十分类似,同样时通过
-
-
图ic_done_anim_000与图ic_plus_anim_030分别代表两种不同的状态。同时,我们也给这两种状态增加了ID来进行区分,下面就可以使用
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
有了animated-selector之后,只需要把它应用到一个ImageView上即可。同时,在代码中设置不同的点击状态。在Android中,通常使用如下所示的系统熟悉来设置切换状态。
private static final int[] STATE_CHECKED = new int[]{android.r.attr.state_checked};
private static final int[] STATE_UNCHECKED = new int[] {};
当点击时,通过setImageState方法来改变一个背景状态图,完整代码如下所示。
package test.chenj.study_12;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class StateListAnimatorActivity extends AppCompatActivity {
private boolean mIsCheck;
private static final int[] STATE_CHECKED = new int[]{android.R.attr.state_checked};
private static final int[] STATE_UNCHECKED = new int[]{};
private ImageView mImageView;
private Drawable mDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_state_list_animator);
mImageView = (ImageView)findViewById(R.id.image);
mDrawable = getResources().getDrawable(R.drawable.fab_anim);
mImageView.setImageDrawable(mDrawable);
}
public void anim(View view) {
if (mIsCheck) {
mImageView.setImageState(STATE_CHECKED, true);
mIsCheck = false;
} else {
mImageView.setImageState(STATE_UNCHECKED, true);
mIsCheck = true;
}
}
}