第七章 Android动画机制与技巧

Android属性动画

    private void objectAnimatorText1() {
        setContentView(R.layout.activity_main);
        final Button button = (Button) findViewById(R.id.bt);
        LinearLayout linearLayout = findViewById(R.id.ll);
        final TextView textViewFirst = linearLayout.findViewById(R.id.tv_first);
        button.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
            @Override
            public void onClick(View v) {
                /**
                 * 操作的属性必须要有set、get方法,不然无法起效
                 */
                ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(button, "translationX", 300);
                objectAnimator1.start();
                /**
                 * 通过插值器,可以定义动画变化速率,类似于物理中的加速度
                 *
                 *      线性插值器:在持续时间内,单位时间所移动的距离都是一样的
                 *      加速度插值器:单位时间内所移动的距离越来越快
                 */
                objectAnimator1.setInterpolator();
                objectAnimator1.addListener(new AnimatorListenerAdapter() {
                    /**
                     * 大部分我们只关心动画结束事件
                     */
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                    }
                });

                /**
                 * 操作的属性没有set、get方法,通过自定义一个属性类或者包装类,来间接给这个属性增加set、get方法
                 */
                WrapperView wrapperView = new WrapperView(button);
                ObjectAnimator objectAnimator2 = ObjectAnimator.ofInt(wrapperView, "width", 300);
                objectAnimator2.start();

                /**
                 * 类似视图动画中的AnimationSet
                 */
                PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationX", 300f);
                PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
                PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
                ObjectAnimator.ofPropertyValuesHolder(button, holder1, holder2, holder3).setDuration(1000).start();

                /**
                 * ValueAnimator本身不提供任何动画效果,更像是一个数值发生器,
                 */
                ValueAnimator animator = ValueAnimator.ofInt(0, 400);
                animator.setTarget(button);
                animator.setDuration(1000).start();
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        /**
                         * 可以使用该数值做想做的事
                         */
                        int animatedValue = (int) animation.getAnimatedValue();
                        Log.i(TAG, "onAnimationUpdate: "+animatedValue);
                        /**
                         * 计时器动画
                         */
                        textViewFirst.setText(String.valueOf(animatedValue));
                    }
                });
                /**
                 * Android3.0之后,Geogle给View增加了这样一种简易的方式驱动属性动画
                 */
                button.animate().alpha(0).y(300).setDuration(3000)
                        .withStartAction(new Runnable() {
                            @Override
                            public void run() {

                            }
                        }).withEndAction(new Runnable() {
                    @Override
                    public void run() {

                    }
                }).start();

                /**
                 * 自定义动画
                 */
                MyAnimation myAnimation = new MyAnimation();
                myAnimation.setDuration(1000);
                button.startAnimation(myAnimation);

            }
        });

        /**
         * 布局动画
         */
        LinearLayout linearLayout = findViewById(R.id.ll);
        ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1);
        scaleAnimation.setDuration(2000);
        /**
         * 第一个参数是需要作用的动画,第二个参数是每个子view显示的delay时间
         * 当viewGroup添加view的时候,通过LayoutAnimationController定义一个子view的过渡效果
         */
        LayoutAnimationController controller = new LayoutAnimationController(scaleAnimation, 0.5f);
        /**
         * delay时间不为0的时候可以设置这个
         *
         * 子view出现的顺序:
         *      ORDER_NORMAL: 顺序
         *      ORDER_RANDOM: 随机
         *      ORDER_REVERSE: 反序
         */
        controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
        linearLayout.setLayoutAnimation(controller);

    }

    private static class WrapperView{
        private View mTarget;
        public WrapperView(View target){
            mTarget = target;
        }
        public void setWidth(int width){
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }
        public int getWidth(){
            return mTarget.getLayoutParams().width;
        }
    }

自定义动画

/**
 * 自定义动画
 */
public class MyAnimation extends Animation {

    private Camera mCamera;
    private int mCenterWidth;
    private int mCenterHeight;
    private int mRotateY = 45;
    public MyAnimation(){
        mCamera = new Camera();
    }
    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        setDuration(2000);
        /**
         * 动画结束后保留状态
         */
        setFillAfter(true);
        setInterpolator(new BounceInterpolator());
        mCenterWidth = width/2;
        mCenterHeight = height/2;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        /**
         * 获得当前的矩阵对象
         */
        Matrix matrix = t.getMatrix();
        mCamera.save();
        mCamera.rotateY(mRotateY*interpolatedTime);
        /**
         * 将旋转变换作用到Matrix
         */
        mCamera.getMatrix(matrix);
        mCamera.restore();
        /**
         * 通过pre方法设置矩阵作用前的偏移量来改变旋转中心
         */
        matrix.preTranslate(mCenterWidth, mCenterHeight);
        matrix.postTranslate(-mCenterWidth, mCenterHeight);
    }
}

下拉展开动画

实现类似商城购物车里的删除、收藏按钮。

    private void dropAnimatorText() {
        setContentView(R.layout.drop);
        LinearLayout ll_click = findViewById(R.id.ll_click);
        final LinearLayout hidden_view = findViewById(R.id.hidden_view);
        // 获取像素密度
        mDensity = getResources().getDisplayMetrics().density;
        /**
         * 获取布局的高度,40dp是布局的高度,这里转化为了像素值
         *
         *   因为view还没有测量完毕,所以获取不到高
         */
        Log.i(TAG, "dropAnimatorText: "+hidden_view.getMeasuredHeight());
        mViewHeight = (int) (mDensity * 40 + 0.5);
        ll_click.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (hidden_view.getVisibility() == View.GONE){
                    animataOpen(hidden_view);
                }else {
                    animataClose(hidden_view);
                }
            }
        });
    }

    private void animataClose(final LinearLayout hidden_view) {
        int height = hidden_view.getHeight();
        ValueAnimator animator = createDropAnimator(hidden_view, height, 0);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                hidden_view.setVisibility(View.GONE);
            }
        });
        animator.start();
    }

    private void animataOpen(View hidden_view) {
        hidden_view.setVisibility(View.VISIBLE);
        ValueAnimator animator = createDropAnimator(hidden_view, 0, mViewHeight);
        animator.start();
    }

    private ValueAnimator createDropAnimator(final View hidden_view, int start, int end) {
        ValueAnimator animator = ValueAnimator.ofInt(start, end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int animatedValue = (int) animation.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams = hidden_view.getLayoutParams();
                layoutParams.height = animatedValue;
                hidden_view.setLayoutParams(layoutParams);
            }
        });
        return animator;
    }

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值