属性动画案例一(基础动画与飘心动画)

之前写过一个 基本属性动画 的简单介绍,这里再简单试用一下。属性动画的案例有很多很多都是特别炫的,其实重点还是思路,这里就提供一些属性动画的思路,思路可能很粗糙,但是效果实现了~

先看一下今天实现的第一种效果。


setAnim.gif

这里是两张图片,用动画集合简单的实现了一个动画效果。分析一下需要用到的动画,商品页面有:透明动画,旋转动画,还有一个缩放动画,暂时就能看出这么多,看一下代码实现。

        //透明度动画
        ObjectAnimator firstAlphaAnim = ObjectAnimator.ofFloat(first_view, "alpha", 1.0f, 0.7f);
        firstAlphaAnim.setDuration(300);
        //旋转动画1
        ObjectAnimator firstRotationXanim = ObjectAnimator.ofFloat(first_view, "rotationX", 0f,20f,0f);
        firstRotationXanim.setDuration(600);
        //缩放动画
        ObjectAnimator firstScaleXAnim = ObjectAnimator.ofFloat(first_view, "ScaleX", 1.0f, 0.8f);
        firstScaleXAnim.setDuration(300);
        ObjectAnimator firstScaleYAnim = ObjectAnimator.ofFloat(first_view, "ScaleY", 1.0f, 0.8f);
        firstScaleYAnim.setDuration(300);
        AnimatorSet set = new AnimatorSet();
        //一起执行
        set.playTogether(
                firstScaleXAnim,
                firstScaleYAnim,
                firstAlphaAnim,
                firstRotationXanim
        );
        set.start();
setAnim1.gif

这里发现,应该是还少一个平移动画,才能让view贴到屏幕上边。由于刚才缩放高度减少了0.2*view的高度,上下各0.1,所以我们需要向上平移0.1个控件的高度。

        //由于缩放造成离顶部有一个距离,需要平移
        ObjectAnimator firstTranslationYAnim = ObjectAnimator.ofFloat(first_view, "translationY", 0f, -0.1f*first_view.getHeight());
        firstTranslationYAnim.setDuration(300);
setAnim2.gif

好了,一个view解决了,剩下就是规格页面的一个显示并平移,规格页面初始是不显示的,在商品页面动画开始的时候,显示规格页面,并从自己的底部移动到自己原来的位置。

        //第二个view和第一个view动画同时开始执行
        ObjectAnimator secondTranslationYAnim = ObjectAnimator.ofFloat(second_view, "translationY", second_view.getHeight(), 0f);
        secondTranslationYAnim.setDuration(300);
        secondTranslationYAnim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                second_view.setVisibility(View.VISIBLE);
                bt.setClickable(false);
                bt1.setClickable(false);
            }
        });

最后大功告成。基本的属性动画又使用了一次,是不是不过瘾,发现这个Demo 有两个按钮,之前一直都是点的 显示 按钮会出现基础动画的使用,那个赞一个是什么鬼。

Anim3.gif

这种常见的刷鲜花效果,这里依旧是属性动画实现的,还记得在 基本属性动画中说过的一个估值器,可以让View以抛物线的轨迹移动,这里也是用到了估值器,一起来看一下怎么实现的把~
首先我们在点击按钮是需要添加心图片,并简单的做了内存优化。一些值的初始化就在 源码 中看吧

    //点击按钮时调用
    public void addLoveIcon(){
        final ImageView iv ;
        //添加心形,并开始执行动画
        iv= (ImageView) Recycle();
        iv.setImageDrawable(drawables[random.nextInt(3)]);
        //将iv添加到父容器底部、水平居中位置
        iv.setLayoutParams(params);
        addView(iv);
        //开始属性动画:平移、透明度渐变、缩放动画
        AnimatorSet set = getAnimator(iv);

        //监听动画执行完毕,将iv移除或者复用
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                removeView(iv);
            }
        });
        set.start();
    }

    List<View> list=new ArrayList<>();
    //重新removeView将要删除的View保存起来
    @Override
    public void removeView(View view) {
        list.add(view);
        super.removeView(view);
    }
    //添加view的时候先看有没有之前保存的imageView
 private View Recycle() {
        if (list.isEmpty()) {
            ImageView iv = new ImageView(getContext());
//            {//固定位置
//              startX=(mWidth - dWidth) / 2;
//
//            }
            {//随机位置
                startX = random.nextInt(mWidth);
                iv.setX(startX);
                iv.setY(mHeight - dHeight);
            }
            return iv;
        } else {
            View v = list.get(0);
            //这里是在复用的时候如果执行第一个缩放动画,位置会有问题,所以这里设置一下初始位置
//          {//固定位置
//              startX=(mWidth - dWidth) / 2;
//              v.setX(startX);
//              v.setY(mHeight - dHeight);
//          }
            {//随机位置
                startX = random.nextInt(mWidth);
                v.setX(startX);
                v.setY(mHeight - dHeight);
            }
            list.remove(v);
            return v;
        }
    }

这里的固定位置和随机位置是图片初始的位置,现在是随机位置,如果要使用固定为在需要将这里面代码重新注释,把随机位置的代码块注释掉,然后把源码 81行 82 行 params的设置解开。在添加的时候调用getAnimator()来设置imageView动画。

    // 得到一个iv的动画集合
    private AnimatorSet getAnimator(ImageView iv) {
        //平移、透明度渐变、缩放动画
        //1.alpha动画
        ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 0.3f,1f);
        //2.缩放动画
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 0.5f,1f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 0.5f,1f);
        //三个动画同时执行
        AnimatorSet enter = new AnimatorSet();
        enter.setDuration(200);
        enter.playTogether(alpha,scaleX,scaleY);

        //设置平移的曲线动画---贝塞尔曲线
        ValueAnimator bezierAnimator = getBezierValueAnimator(iv);

        AnimatorSet set = new AnimatorSet();
        //按序列执行
        set.playSequentially(enter, bezierAnimator);
        //加速因子,使用插值器
        set.setInterpolator(interpolators[random.nextInt(4)]);
        set.setTarget(iv);
        return set;
    }

先执行原地的缩放,透明度变化的动画,再执行估值器的动画。

    //得到一个贝塞尔曲线动画
    private ValueAnimator getBezierValueAnimator(final ImageView iv) {
        //根据贝塞尔公式确定四个点(起始点p0,拐点1p1,拐点2p2,终点p3)
        PointF pointF0 = new PointF(startX, mHeight - dHeight);//屏幕宽度随机的为起点
        PointF pointF3 = new PointF(random.nextInt(mWidth), 0);
        PointF pointF1 = getPointF(1);
        PointF pointF2 = getPointF(2);
        //估值器Evaluator,来控制view的行驶路径(不断地修改point.x,point.y)
        BezierEvaluator evaluator = new BezierEvaluator(pointF1, pointF2);
        //属性动画不仅仅可以改变view的属性,还可以改变自定义的属性(比如Point)
        ValueAnimator animator = ValueAnimator.ofObject(evaluator, pointF0, pointF3);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF pointF = (PointF) animation.getAnimatedValue();
                iv.setX(pointF.x);
                iv.setY(pointF.y);
                iv.setAlpha(1 - animation.getAnimatedFraction());//1~0 百分比
            }
        });

        animator.setDuration(4000);
        return animator;
    }

这里是对 起点,终点,和两个控制点的初始化,这样就可以形成一个三阶贝塞尔曲线,这里会间接的把四个点传过去,在BezierEvaluator计算X,Y的值,直接套公式,通过监听获取返回的坐标值。
最后附上 源码

这里只是属性动画基本的一个使用,如果其中有错误还请指出,我会尽快修改文章,并改正自己的理解,谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容