Android动画(实现抛物线运动)

Android动画实现包括视图动画以及属性动画。其中比较新颖的自然是5.X系统下的矢量图动画,这个小编也仅仅只是做了初步的了解,毕竟连矢量图的生成还没有掌握好,并且漂亮的矢量图也必须借助工具来实现。本次内容主要是根据“抛物线运动”的个人实现思路来展开描述的,最终实现肯定是各有方案的。


1.开发中常用的动画框架:

  • AlphaAnimation 透明度动画
  • RotateAnimation 旋转动画
  • TranslateAnimation 位移动画
  • ScaleAnimation 缩放动画

基于以上动画的实现可以实现集合动画,主要是利用AnimationSet.addAnimation();将其组合起来实现。动画执行期间(包括动画的启动,取消,结束以及循环)的监听可以是.setAnimationListener(new Animation.AnimationListener(){};当然,由于我们往往更多关注的是动画结束时候的处理,所以可以直接用.setAnimationListener(new Animation.AnimationListenerAdapter(){};


2.属性动画分析

到这里得理解的一点是,既然通过以上的动画框架接口已实现很好的视图动画效果了,那为什么还要去研究属性动画呢,原因是其动画框架仅能实现显示效果,但无法响应其他事件。故Android3.0之后更多的是用AnimationSet与ObjectAnimator(个体动画属性的更改)配合使用。其中ObjectAnimator常用的动画属性值有

  • translationX、translationY:控制视图的偏移位置(距离左上角)
  • rotation、rotationX、rotationY:控制视图的2D、3D旋转
  • scaleX、scaleY:控制视图水平或者垂直方向的缩放
  • pivotX、pivotY:控制视图旋转或者缩放的支点位置
  • x、y:控制视图的最终位置
  • alpha:控制视图的透明度
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 500);
animator.setDuration(1000);
animator.start();

注意,以上代码实现的是view在x轴方向上移动至距离左上角水平位置为500px的地方,而不是在原基础上向x轴正方向移动500px。如果我们考虑实现多个动画属性能够同时进行,那么可以借助PropertyValueHolder实现,如下代码片段就实现了view在水平偏移的同时进行了垂直方向上的位置偏移。

PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 500);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("translationY", 500);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2).setDuration(1000).start();

在这里如果我们希望动画的集合能够有一定的顺序实现,而不是单一的并发进行。那么除了给每个独立的动画设置动画监听以外我们可以继续用AnimatorSet(注意:这里不是AnimationSet)。其可以通过playogether()、playSequentially()、animSet.Play().with()、befor()、after()分别控制动画的工作方式,从而可好的控制动画的播放顺序。如下实现view同时执行位移,旋转以及缩放的动画效果。其他方法可自行尝试。

ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 500);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "rotationY", 0, 180);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleX", 1.5f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1, animator2, animator3);
set.start();

除了通过以代码的形式设置属性动画以外,其实我们还习惯通过.xml来实现其一样的效果。如下所示实现视图的透明渐变和引用。

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" > 
    <alpha 
        android:duration="1000"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:interpolator="@android:anim/accelerate_interpolator" /> 
</set>
Animator anim = AnimatorInflater.loadAnimator(R.drawable.animXml);
anim.setTarget(view);
anim.start;

3.布局动画

表示小编基本上没用过布局动画,所谓布局动画就是在ViewGroup添加子View时所呈现出来的一个动画过渡效果。在ViewGroup的.xml当中可以直接设置属性android:animateLayoutChanges=”true”来启动渐显的过渡效果。如果想自定义过渡效果可以类似以下代码实现:

Animator anim = AnimatorInflater.loadAnimator(R.drawable.animXml);// 定义动画内容
LayoutAnimationController lac = new LayoutAnimationController(anim );
/* 
 * LayoutAnimationController.ORDER_RANDOM 随机
 * LayoutAnimationController.ORDER_NORMAL 顺序
 * LayoutAnimationController.ORDER_REVERSE 反序
 * /
lac.setOrder(LayoutAnimationController.ORDER_RANDOM);
lac.setDelay(0.5f);
view.setLayoutAnimation(lac);

4.插值器Interpolators

对于插值器,不得不说这才是个狠角色。因为小编的抛物线运动轨迹就是通过插值器的速率变换来实现的。可能有些人还不了解插值器是什么,其实最常见的插值器就是我们在定义动画时,所引用到的加速减速以及弹回等改变动画运行状态的工具。而Interpolators主要包含以下几种插值器。

Interpolator对象资源ID功能作用
AccelerateDecelerateInterpolator@android:anim/accelerate_decelerate_interpolator先加速再减速
AccelerateInterpolator@android:anim/accelerate_interpolator加速
AnticipateInterpolator@android:anim/anticipate_interpolator先回退一小步然后加速前进
AnticipateOvershootInterpolator@android:anim/anticipate_overshoot_interpolator在上一个基础上超出终点一小步再回到终点
BounceInterpolator@android:anim/bounce_interpolator最后阶段弹球效果
CycleInterpolator@android:anim/cycle_interpolator周期运动
DecelerateInterpolator@android:anim/decelerate_interpolator减速
LinearInterpolator@android:anim/linear_interpolator匀速
OvershootInterpolator@android:anim/overshoot_interpolator快速到达终点并超出一小步最后回到终点

而每一种插值器自然而然的也都是继承自Interpolators实现,并重写其核心方法public float getInterpolation(float input){};该函数参数input值为插值器x轴方向上0.0f到1.0f的变换过程。对应的返回值即代表当前的动画运行速率。根据这一点,我们只要友好地编上一条自定义速率变换方程就可以轻松地实现类似抛物线的动画了。当然,这种实现比较抽象,前提是必须先理解速率变换给动画运行所带来的影响,比如说当速率是负数的时候,会改变动画的运动方向。下面给到小编自己通过AnticipateInterpolator来实现view呈类似抛物线运动的效果及代码。

实现效果演示

为了方便理解,在了解代码具体实现之前请先了解相关AnticipateInterpolator速率变换轨迹如下。具体可参照 http://my.oschina.net/banxi/blog/135633?fromerr=uv67kzf9#OSC_h2_7 (包括其他插值器对应的速率轨迹图详细注解)。

AnticipateInterpolator轨迹

@OnClick({R.id.reddot_btn_parabola})
private void mOnClick(View view) {
    switch (view.getId()) {
        case R.id.reddot_btn_parabola:
            // 每点击一次按钮就给父容器mMainRly(RelativeLayout)添加一个小球
            final ImageView img = getClickDot(view, 30);
            mMainRly.addView(img);
            // 获取底下购物车的位置
            final PointF end = getViewPointF(mShopCartImg);
            ObjectAnimator animator1 = ObjectAnimator.ofFloat(img, "x", end.x);
            ObjectAnimator animator2 = ObjectAnimator.ofFloat(img, "y", end.y);
            animator2.setInterpolator(new AnticipateInterpolator(3.0f));
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(800);
            animatorSet.playTogether(animator1, animator2);
            animatorSet.start();

            animatorSet.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    // 小球运行结束后从父容器中移除
                    mMainRly.removeView(img);
                }
            });
            break;
    }
}

/**
 * @param v    被点击的视图(用于采集球的位置)
 * @param size 球体大小
 * @return 根据位置返回新的球
 */
private ImageView getClickDot(View v, int size) {
    ImageView dotIv = new ImageView(this);
    ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(size, size);
    dotIv.setLayoutParams(params);
    dotIv.setX(v.getX() + v.getWidth() / 2 - size / 2);
    dotIv.setY(v.getY() + v.getHeight() / 2 - size / 2);
    dotIv.setImageResource(R.drawable.vector_reddot_small);
    return dotIv;
}

/**
 * @param view 取点视图
 * @return 获取视图坐标点
 */
private PointF getViewPointF(View view) {
    PointF pointF = new PointF();
    pointF.x = view.getX() + view.getWidth() / 2;
    pointF.y = view.getY() + view.getHeight() / 2;
    return pointF;
}

5.自定义动画

自定义动画效果继承自Animation,需要重写initialize();以及applyTransformation();两个方法,其中initialize();应用于动画的一些属性初始化,而applyTransformation();才是自定义动画的核心过程。具体的实现案例“3D翻转”效果可参考http://chroya.iteye.com/blog/828094

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要在Scratch中实现抛物线运动,需要使用计时和移动积木。首先,创建一个计时,然后设置一个变量来跟踪时间。接下来,使用运动积木让角色沿着x轴和y轴移动。最后,使用公式 (x = at^2 + bt + c) 和 (y = dt^2 + et + f) 来计算角色的位置,其中 a,b,c,d,e,f是常量。 ### 回答2: 抛物线运动是指一个物体在受到重力影响的情况下,沿着抛物线轨迹运动的现象。在Scratch中,我们可以通过利用角度与重力的概念,来实现抛物线运动的效果。 首先,我们需要创建一个角色,代表抛物线运动的物体。可以选择一个合适的图标来代表该角色,并设置其初始位置。接下来,我们需要定义相关的变量。 我们可以定义一个变量来表示物体在x轴方向上的位移,例如变量名为“x”。初始时,将其设为0。我们还可以定义一个变量来表示物体在y轴方向上的位移,例如变量名为“y”。初始时,将其设为0。 然后,我们需要设置物体的运动规律。在每一帧中,物体在x轴方向上的位移都应该增加一个固定值,例如1,以保持匀速直线运动。我们可以使用Scratch中的“改变x by 1”积木块实现这个功能。 接下来,我们需要根据物体的位置来计算物体在y轴方向上的位移。由于抛物线运动是受到重力影响的,物体在y轴方向上的位移应随时间递增,且增量随时间增大而增大。为了实现这个效果,我们可以使用一个循环,让每一帧中的y轴位移都增加一个较大的数值。例如,在每一帧中,可以使用“改变y by 10”积木块来让y轴位移增加10个单位。 最后,我们需要添加一个条件,以停止物体的运动。一般来说,当物体的y轴位移超过一定的值,或者物体的x轴位移超过一定的范围时,我们可以认为物体已经完成了抛物线运动。我们可以将这个条件写入一个判断语句中,例如,“如果y大于100 或者 x小于-200,则停止运动”。在满足这个条件时,我们可以使用Scratch中的“停止所有”积木块来停止物体的运动。 通过以上的步骤,我们就可以在Scratch中实现抛物线运动的效果。通过调节不同的参数,如角度、重力等,我们可以创建不同形状和大小的抛物线运动物体。 ### 回答3: 使用Scratch实现抛物线运动可以通过以下步骤实现: 1. 创建角色:在Scratch的舞台中创建一个角色,用于表示抛物线运动的物体。 2. 设置角色初始位置:将角色放置在舞台的起始位置,确保它位于抛物线的起点。 3. 设置角色的运动轨迹:点击角色,选择“运动”类别,在运动模块中选择“移动到x: [] y: []”模块。根据抛物线的方程,通过改变x和y的值来实现运动的轨迹。 4. 添加重力效果:为了实现抛物线运动,我们需要加入重力的效果。点击角色,选择“运动”类别,在运动模块中选择“重力(0.2)加速度”模块。调整加速度的值以获得所需的抛物线效果。 5. 添加弹跳效果:如果需要让角色在抛物线的顶点反弹,可以点击角色,选择“事件”类别,然后选择“当接触边缘时反弹”模块。 6. 重复运动:使用“重复”模块或“循环”模块,使角色重复执行运动的轨迹,以实现持续的抛物线运动。 7. 角色动作:可以为角色添加动作,如旋转、改变大小等,以增加视觉效果。 总结:使用Scratch可以通过设置角色的初始位置、运动轨迹和重力效果,结合重复运动实现抛物线运动。此外,你还可以根据需要添加其他特效和动作来提升抛物线运动的视觉效果。以上步骤简要介绍了如何使用Scratch实现抛物线运动

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值