文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android动画-属性动画

2022-06-06 13:27

关注

属性动画

所谓属性动画,就是改变对象Object的属性来实现动画过程。属性动画是对View的动画的扩展,通过它可以实现更多漂亮的动画效果。同时属性动画的作用对象不仅仅是View,任何对象都可以。
属性动画的作用效果就是:在一个指定的时间段内将对象的一个属性的属性值动态地变化到另一个属性值。

ObjectAnimator
ObjectAnimator
            .ofFloat(mImageView, "rotationY", 0f, 360f)
            .setDuration(2000)
            .start();

ObjectAnimtor可以用ofInt、ofFloat、ofObject等静态方法,传入动画作用的目标Object、属性字段、属性开始值、属性中间值、属性结束值等参数来构造动画对象。 通过不断去调用对象属性的setter方法改变属性值,不断重绘实现动画过程.
xml实现属性动画,工程的res目录下创建animator文件,创建xml文件


private void startXmlPropertyAnimator() {
    Animator animator = AnimatorInflater.loadAnimator(getApplicationContext(),R.animator.property_animator);
    animator.setTarget(mImageView);
    animator.start();
}

当然也可以通过动画组合的形式来执行多个动画。AnimationSet

   Animator scaleXAnimator = ObjectAnimator.ofFloat(mImageView, "scaleX", 1, 0.5f);
    scaleXAnimator.setDuration(2000);
    Animator scaleYAnimator = ObjectAnimator.ofFloat(mImageView, "scaleY", 1, 0.5f);
    scaleYAnimator.setDuration(2000);
    Animator rotationXAnimator = ObjectAnimator.ofFloat(mImageView, "rotationX", 0, 360);
    rotationXAnimator.setDuration(2000);
    Animator rotationYAnimator = ObjectAnimator.ofFloat(mImageView, "rotationY", 0, 360);
    rotationYAnimator.setDuration(2000);
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.play(scaleXAnimator)
            .with(scaleYAnimator)
            .before(rotationXAnimator)
            .after(rotationYAnimator);
    animatorSet.start();

AnimatorSet通过before、with、after三个方法可以组合多个属性动画,with表示与给定动画同时执行,before在给定动画执行之前执行,after表示在给定动画执行之后执行.
属性动画也可以在xml定义动画集

ValueAnimator

ValueAnimator是ObjectAnimator的父类,它继承自Animator。ValueAnimaotor同样提供了ofInt、ofFloat、ofObject等静态方法,传入的参数是动画过程的开始值、中间值、结束值来构造动画对象。可以将ValueAnimator看着一个值变化器,即在给定的时间内将一个目标值从给定的开始值变化到给定的结束值。在使用ValueAnimator时通常需要添加一个动画更新的监听器,在监听器中能够获取到执行过程中的每一个动画值。ValueAnimator的使用一般会结合更新监听器AnimatorUpdateListener,大多数时候是在自定义控件时使用。

在这里插入图片描述

下面看个列子
当点击箭头,会展开文本内容,当然同时伴随着动画出现。

 private void anim() {
        // 指示器旋转
        ValueAnimator valueAnimator1 = isClosed
                ? ValueAnimator.ofFloat(180, 0)
                : ValueAnimator.ofFloat(0, 180);
        valueAnimator1.setDuration(500);
        valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                mIvIndicator.setRotation(value);
            }
        });
        valueAnimator1.start();
        // 打开开关闭操作
        // 内容的高度
        final int answerHeight = mTvAnswer.getMeasuredHeight();
        ValueAnimator valueAnimator2 = isClosed
                ? ValueAnimator.ofInt(-answerHeight, 0)
                : ValueAnimator.ofInt(0, -answerHeight);
        valueAnimator2.setDuration(500);
        final MarginLayoutParams params = (MarginLayoutParams) mTvAnswer.getLayoutParams();
        valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 接收内容的高度
                int value = (int) animation.getAnimatedValue();
                params.bottomMargin = value;
                // 设置高度变化
                mTvAnswer.setLayoutParams(params);
            }
        });
        valueAnimator2.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                //记录动画结束的状态
                isClosed = !isClosed;
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        valueAnimator2.start();
    }
TypeEvaluator

属性动画计算器。ObjectAnimator和ValueAnimator都有ofObject方法,传入的都有一个TypeEvaluator类型的参数.TypeEvaluator是一个接口,有个方法avaluate

public T evaluate(float fraction, T startValue, T endValue);

要用属性动画来执行复杂对象的动画过程,就需要自定义TypeEvaluator,实现动画逻辑。

public class Circle {
    private int raduis;         // 半径
    private int color;          // 颜色
    private int elevation;      // 高度
    public Circle(int raduis, int color, int elevation) {
        this.raduis = raduis;
        this.color = color;
        this.elevation = elevation;
    }
    public int getRaduis() {
        return raduis;
    }
    public void setRaduis(int raduis) {
        this.raduis = raduis;
    }
    public int getColor() {
        return color;
    }
    public void setColor(int color) {
        this.color = color;
    }
    public int getElevation() {
        return elevation;
    }
    public void setElevation(int elevation) {
        this.elevation = elevation;
    }
}

自定义控件CircleView,将Circle作为它的一个属性:

public class CircleView extends View {
    private Circle circle;
    private Paint mPaint;
    public CircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        circle = new Circle(168, Color.RED, 0);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setElevation(circle.getElevation());
        mPaint.setColor(circle.getColor());
        canvas.drawCircle(getMeasuredHeight() / 2, getMeasuredHeight() / 2, circle.getRaduis(), mPaint);
    }
    public void setCircle(Circle circle) {
        this.circle = circle;
        postInvalidate();
    }
    public Circle getCircle() {
        return circle;
    }
}

方法的调用,创建三个圆,由半径168到300到450依次执行,当然还有颜色的变化,红色-绿色-蓝色,高度的变化。
ObjectAnimator使用:注意属性动画是通过反射获取,所以属性的名字是circle

private void start1() {
    Circle startCircle = new Circle(168, Color.RED, 0);
    Circle middleCircle = new Circle(300, Color.GREEN, 15);
    Circle endCircle = new Circle(450, Color.BLUE, 30);
    ObjectAnimator.ofObject(mCircleView, "circle", new CircleEvaluator(), startCircle, middleCircle, endCircle)
            .setDuration(5000)
            .start();
}

ValueAnimator使用:

private void start2() {
    Circle startCircle = new Circle(168, Color.RED, 0);
    Circle middleCircle = new Circle(300, Color.GREEN, 15);
    Circle endCircle = new Circle(450, Color.BLUE, 30);
    ValueAnimator valueAnimator = ValueAnimator.ofObject(new CircleEvaluator(), startCircle, middleCircle, endCircle);
    valueAnimator.setDuration(5000);
  //通过监听变化,给view赋值
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Circle circle = (Circle) animation.getAnimatedValue();
            mCircleView.setCircle(circle);
        }
    });
    valueAnimator.start();
}

image.png
该文摘自:https://juejin.im/entry/58b3f07e570c35006932b067


作者:名字是真的不好起


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯