您的位置:首页 > 移动开发 > Android开发

Android属性动画

2016-02-15 16:11 423 查看
属性动画是Android3.0之后,Google提出的全新的动画框架,帮助开发者实现更加丰富的动画效果。

在属性动画框架中使用最多的就是AnimatorSet和ObjectAnimator,使用ObjectAnimator进行更精细化控制,只控制一个对象的一个属性值,而使用多个ObjectAnimator组合到AnimatorSet形成一个动画。值得注意的是,属性动画是通过调用属性的get,set的方法来真实控制一个view的属性值,因此强大的属性动画框架,基本可以实现所有的动画效果。

属性动画框架和之前动画框架有什么区别呢?

比如将一个button向右平移200个单位,这时候如果用之前的动画框架,那button的click就失效了,如果用属性动画,那click还是有效的,因为属性动画是真正的改变view的属性。

一些常用的属性名称:

translationX和translationY:这两个属性作为一种增量来控制着view对象从它布局容器的左上角坐标偏移的位置。

rotation,rotationX,rotationY:这三个属性控制view对象围绕支点进行2D和3D旋转。

scaleX和scaleY:这个两个属性控制view围绕它的支点进行2D缩放。

pivotX和pivotY:这两个属性控制着view对象的支点位置,围绕这个支点进行旋转和缩放变化处理,默认情况下,该支点的位置就是view对象的中心点。

x和y:这是两个简单实用属性,它描述了view对象在他的容器中的最终位置,它是最初的左上角坐标和translationX,translationY值的累计和。

alpha:它表示view对象的alpha透明度,默认值是1(不透明),0代表完全透明(不可见)

下面介绍一个ObjectAnimator使用例子,当属性动画与自定义view相结合,先上效果:



上代码:

public class MenuView extends ViewGroup implements View.OnClickListener {

private View centerView;
private boolean isOpen;
private OnMenuClickListener mListener;

public MenuView(Context context) {
super(context);
}

public MenuView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public MenuView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (i == childCount - 1)
child.setId(-1);
else
child.setId(i);
child.setOnClickListener(this);
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
centerView = getChildAt(childCount - 1);
for (int i = 0; i < childCount; i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
setMeasured
bcdc
Dimension(centerView.getMeasuredWidth() * 3, centerView.getMeasuredHeight() * 3);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
for (int i = 0; i < childCount - 1; i++) {
View otherView = getChildAt(i);
otherView.layout(getMeasuredWidth() / 2 - centerView.getMeasuredWidth() / 2 + 10, getMeasuredHeight() / 2 - centerView.getMeasuredHeight() / 2 + 10,
getMeasuredWidth() / 2 + centerView.getMeasuredWidth() / 2-10, getMeasuredHeight() / 2 + centerView.getMeasuredHeight() / 2-10);
}
centerView.layout(getMeasuredWidth() / 2 - centerView.getMeasuredWidth() / 2, getMeasuredHeight() / 2 - centerView.getMeasuredHeight() / 2,
getMeasuredWidth() / 2 + centerView.getMeasuredWidth() / 2, getMeasuredHeight() / 2 + centerView.getMeasuredHeight() / 2);
}

@Override
public void onClick(View v) {

switch (v.getId()) {
case -1:
if (isOpen)
closeMenu();
else
openMenu();
isOpen = !isOpen;
break;

default:
if (mListener != null)
mListener.onClick(v.getId());
break;
}
}

private void openMenu() {
//center
ObjectAnimator a0 = ObjectAnimator.ofFloat(centerView, "alpha", 1f, 0.5f);
//top
ObjectAnimator a1 = ObjectAnimator.ofFloat(getChildAt(0), "translationY", -centerView.getMeasuredHeight());
//right
ObjectAnimator a2 = ObjectAnimator.ofFloat(getChildAt(1), "translationX", centerView.getMeasuredWidth());
//bottom
ObjectAnimator a3 = ObjectAnimator.ofFloat(getChildAt(2), "translationY", centerView.getMeasuredHeight());
//left
ObjectAnimator a4 = ObjectAnimator.ofFloat(getChildAt(3), "translationX", -centerView.getMeasuredWidth());
AnimatorSet set = new AnimatorSet();
set.setDuration(500);
set.setInterpolator(new BounceInterpolator());
set.playTogether(a0, a1, a2, a3, a4);
set.start();
}

private void closeMenu() {
//center
ObjectAnimator a0 = ObjectAnimator.ofFloat(centerView, "alpha", 0.5f, 1f);
//top
ObjectAnimator a1 = ObjectAnimator.ofFloat(getChildAt(0), "translationY", 0);
//right
ObjectAnimator a2 = ObjectAnimator.ofFloat(getChildAt(1), "translationX", 0);
//bottom
ObjectAnimator a3 = ObjectAnimator.ofFloat(getChildAt(2), "translationY", 0);
//left
ObjectAnimator a4 = ObjectAnimator.ofFloat(getChildAt(3), "translationX", 0);
AnimatorSet set = new AnimatorSet();
set.setDuration(500);
set.setInterpolator(new BounceInterpolator());
set.playTogether(a0, a1, a2, a3, a4);
set.start();
}

public void setListener(OnMenuClickListener mListener) {
this.mListener = mListener;
}

public interface OnMenuClickListener {
void onClick(int index);
}
}


ValueAnimator也是属性框架里非常重要的类,顾名思义,这个类跟值有关系,通过值的变化来改变view,ObjectAnimator也是继承ValueAnimator。

ValueAnimator本身并不提供任何动画,它更像一个数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现。

下面介绍一个数字自增长的效果,有点像余额宝,上效果:



上代码:

public class AutoTextView extends TextView {

private ValueAnimator mValueAnimator;

public AutoTextView(Context context) {
super(context);
}

public AutoTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public AutoTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public void setValue(int startValue,int endValue){
mValueAnimator = ValueAnimator.ofInt(startValue,endValue);
setText("$ "+startValue);
}

public void startAnim(){
if (mValueAnimator != null){
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setText("$ "+(Integer)animation.getAnimatedValue());
}
});
mValueAnimator.setDuration(3000);
mValueAnimator.start();
}
}
}


简单吧,属性动画真的很强大。多加练习,可以在自定义view中大有用途。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: