Android:属性动画

Android基础-Day33【Stage02】

1.1 目标

  • 属性动画

1.2 重点

  • 属性动画

1.3 难点

  • 属性动画

2 属性动画

接下来我们学习Android动画中的第三种动画——属性动画(Property Animation)

Animation一般动画就是我们前面学的帧动画和补间动画Animator则是本节要讲的属性动画

2.1 属性动画的简介

2.1.1 为什么要引入属性动画?
  • 补间动画功能比较单调,只有四种动画(透明度,旋转,倾斜和位移)
  • 补间动画针对的对象只是UI控件
  • 补间动画只是改变View的显示效果,不会去改变View的属性

eg:左边的按钮移到右边,但是此时的按钮其实还停留在左边,假如你去点右面的按钮,是不会触发按钮的点击事件的~

2.1.2 属性动画是什么?
  • Andoid 3.0引入,可以说是补间动画的增强版,不止可以实现四种动画效果,可以定义任何属性的变化;
  • 执行动画的对象不只是U控件。可以对任何对象执行动画(不管是否显示在屏幕上)
  • 属性动画通过对目标对象进行赋值来修改其属性,上面那个按钮问题就不存在了~
2.1.3 属性动画相关的API
API说明
Animator创建属性动画的基类,一般不会直接用,一般用他的两个子类!
ValueAnimator上面也说了,属性动画是通过不断地修改值来实现的,而初始值和结束值间的过度动画就是由该类来负责计算的。内部采用一种时间循环的机制来计算值与值之间的动画过度,我们只需将初始值以及结束值提供给该类,并告诉它动画所需时长,该类就会自动帮我们完成从初始值平滑过渡到结束值这样的效果!除此之外,该类还负责管理动画播放次数,播放模式,以及对动画设置监听器等!
ObjectAnimatorValueAnimator的子类,允许我们对指定对象的属性执行动画,用起来更加简单,实际中用得较多。当然某些场合下,可能还是需要用到ValueAnimator
AnimatorSetAnimator的子类,用于组合多个Animator ,并制定多个Animator按照次序播放,还是同时播放
Evaluator告诉动画系统如何从初始值过度到结束值,提供了下述几种Evaluator :
- IntEvaluator :用于计算int类型属性值的计算器
- FloatEvaluator :用于计算float类型属性值的计算器
- ArgbEvaluator :用于计算十六进制形式表示的颜色值的计算器
- TypeEvaluator :计算器的接口,我们可以实现该接口来完成自定义计算器

2.2 ValueAnimator简单使用

2.2.1 使用流程:
  1. 调用ValueAnimator的ofInt(),ofFloat()或ofObject()静态方法创建ValueAnimator实例
  2. 调用实例的setXxx方法设置动画持续时间,插值方式,重复次数等
  3. 调用实例的addUpdateListener添加AnimatorUpdateListener监听器,在该监听器中 可以获得ValueAnimator计算出来的值,你可以值应用到指定对象上
  4. 调用实例的**start()**方法开启动画! 另外我们可以看到ofInt和ofFloat都有个这样的参数:float/int… values代表可以多个值!
2.2.2 使用示例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xH6Os3HI-1659179684549)(MD文档.assets/73537268.jpg)]

代码实现

布局文件:activity_main.xml,非常简单,四个按钮,一个ImageView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ly_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画1" />

    <Button
        android:id="@+id/btn_two"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画2" />

    <Button
        android:id="@+id/btn_three"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画3" />

    <Button
        android:id="@+id/btn_four"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画4" />

    <ImageView
        android:id="@+id/img_babi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@mipmap/img_babi" />

</LinearLayout>

接着到MainActivity.java, 首先需要一个修改View位置的方法,这里调用moveView()设置左边和上边的起始坐标以及宽高!

接着定义了四个动画,分别是:直线移动,缩放,旋转加透明,以及圆形旋转!

然后通过按钮触发对应的动画~

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_one;
    private Button btn_two;
    private Button btn_three;
    private Button btn_four;
    private LinearLayout ly_root;
    private ImageView img_babi;
    private int width;
    private int height;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
    }

    private void bindViews() {
        ly_root = (LinearLayout) findViewById(R.id.ly_root);
        btn_one = (Button) findViewById(R.id.btn_one);
        btn_two = (Button) findViewById(R.id.btn_two);
        btn_three = (Button) findViewById(R.id.btn_three);
        btn_four = (Button) findViewById(R.id.btn_four);
        img_babi = (ImageView) findViewById(R.id.img_babi);

        btn_one.setOnClickListener(this);
        btn_two.setOnClickListener(this);
        btn_three.setOnClickListener(this);
        btn_four.setOnClickListener(this);
        img_babi.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_one:
                lineAnimator();
                break;
            case R.id.btn_two:
                scaleAnimator();
                break;
            case R.id.btn_three:
                raAnimator();
                break;
            case R.id.btn_four:
                circleAnimator();
                break;
            case R.id.img_babi:
                Toast.makeText(MainActivity.this, "不愧是你", Toast.LENGTH_SHORT).show();
                break;
        }
    }


    //定义一个修改ImageView位置的方法
    private void moveView(View view, int rawX, int rawY) {
        int left = rawX - img_babi.getWidth() / 2;
        int top = rawY - img_babi.getHeight();
        int width = left + view.getWidth();
        int height = top + view.getHeight();
        view.layout(left, top, width, height);
    }


    //定义属性动画的方法:

    //按轨迹方程来运动
    private void lineAnimator() {
        width = ly_root.getWidth();
        height = ly_root.getHeight();
        ValueAnimator xValue = ValueAnimator.ofInt(height,0,height / 4,height / 2,height / 4 * 3 ,height);
        xValue.setDuration(3000L);
        xValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 轨迹方程 x = width / 2
                int y = (Integer) animation.getAnimatedValue();
                int x = width / 2;
                moveView(img_babi, x, y);
            }
        });
        xValue.setInterpolator(new LinearInterpolator());
        xValue.start();
    }

    //缩放效果
    private void scaleAnimator(){
        ValueAnimator vValue = ValueAnimator.ofFloat(1.0f, 0.6f, 1.2f, 1.0f, 0.6f, 1.2f, 1.0f);
        vValue.setDuration(1000L);
        vValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
           @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float scale = (Float) animation.getAnimatedValue();
                img_babi.setScaleX(scale);
                img_babi.setScaleY(scale);
            }
        });
       vValue.setInterpolator(new LinearInterpolator());
        vValue.start();
    }


    //旋转的同时透明度变化
    private void raAnimator(){
        ValueAnimator rValue = ValueAnimator.ofInt(0, 360);
        rValue.setDuration(1000L);
        rValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int rotateValue = (Integer) animation.getAnimatedValue();
                img_babi.setRotation(rotateValue);
                float fractionValue = animation.getAnimatedFraction();
                img_babi.setAlpha(fractionValue);
            }
        });
        rValue.setInterpolator(new DecelerateInterpolator());
        rValue.start();
    }

    //圆形旋转
    protected void circleAnimator() {
        width = ly_root.getWidth();
        height = ly_root.getHeight();
        final int R = width / 4;
        ValueAnimator tValue = ValueAnimator.ofFloat(0,
                (float) (2.0f * Math.PI));
        tValue.setDuration(1000);
        tValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 圆的参数方程 x = R * sin(t) y = R * cos(t)
                float t = (Float) animation.getAnimatedValue();
                int x = (int) (R * Math.sin(t) + width / 2);
                int y = (int) (R * Math.cos(t) + height / 2);
                moveView(img_babi, x, y);
            }
        });
        tValue.setInterpolator(new DecelerateInterpolator());
        tValue.start();
    }
}

好的,使用的流程非常简单,先创建ValueAnimator对象,调用ValueAnimator.ofInt/ofFloat 获得,然后设置动画持续时间,addUpdateListener添加AnimatorUpdateListener事件监听, 然后使用参数animationgetAnimatedValue()获得当前的值,然后我们可以拿着这个值 来修改View的一些属性,从而形成所谓的动画效果,接着设置setInterpolator动画渲染模式, 最后调用start()开始动画的播放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值