Android属性动画

属性动画是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);
        }
        setMeasuredDimension(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中大有用途。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值