android 高级动画技巧和数学原理

android有非常成熟的动画系统,程序员可以借助anroid的动画系统设计出匹配商业广告的动画。

android从早期的补间动画发展到今天的属性动画,乃至lottie动画和opengl动画。

补间动画效率应该比属性动画高,但缺点是不改变view属性,比如放大或者移动一个view,view的点击区域并不会随之变化,在某些场合下依然是个选择。属性动画会修改view的属性,这在有时是需要的,如果不是必要,尽量使用属性动画,因为他功能更强大,而且支持非view变化,比如我们需要修改view图片的形状,模仿眼睛眨动或者半闭全闭的动态效果,就离不开属性动画,因为我们不是仅需要修改view,还要修改view的内容。

动画的基础知识点非常多,这里不再赘述,一个综合的例子可以学到很多东西。这里不回顾动画的基础知识,直接应用,如果有看不明白的,可以留言。

PropertyValuesHolder让我们可以把一个复杂的动画分解成位移,放缩,修改颜色,形状等子动画,
Keyframe可以让我们精确的控制每一帧的变化,间隔一定时间的相同的帧可以让我们在动画某个时刻停留固定时间,

为特定的关健帧设置setInterpolator可以增强动感,多个PropertyValuesHolder的组合,让我们可以把各种效果合并在一个动画里,便于精确控制,虽然AnimatorSet也能实现这一点,但是当我们需要先位移,到固定位置后再放缩同时修改形状,然后还原形状和大小,最后回到原位,比如模拟一个机器开心的动画, 把复杂的动画拆解再组合成animator,便于我们精确动画每一帧的变化,启动和结束。

void creatSleep(){
        final View fv = this.findViewById(R.id.fface);
        final View lv = bmcDemoActivity3.this.findViewById(R.id.fleft);
        final View rv = bmcDemoActivity3.this.findViewById(R.id.fright);

        //Keyframe keyframe = Keyframe.ofInt();
        Keyframe keyframe = Keyframe.ofFloat(0,0);
        keyframe.setInterpolator(new DecelerateInterpolator());
        Keyframe keyframe0 = Keyframe.ofFloat(0.1f,-200); //500ms
        Keyframe keyframe1 = Keyframe.ofFloat(0.9f,-200); //4500ms
        keyframe.setInterpolator(new AccelerateInterpolator());
        Keyframe keyframe2 = Keyframe.ofFloat(1f,0);
        PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationY",keyframe,keyframe0
                ,keyframe1,keyframe2);

        Keyframe keyframe00 = Keyframe.ofFloat(0,1.0f);
        Keyframe keyframe01 = Keyframe.ofFloat(0.1f,1.0f); //500
        keyframe01.setInterpolator(new AccelerateInterpolator());
        Keyframe keyframe011 = Keyframe.ofFloat(0.2f,1.5f); //1000
        Keyframe keyframe02 = Keyframe.ofFloat(0.8f,1.5f);  //4000
        keyframe02.setInterpolator(new AccelerateInterpolator());
        Keyframe keyframe03 = Keyframe.ofFloat(0.9f,1.0f);  //4500
        Keyframe keyframe04 = Keyframe.ofFloat(1f,1.0f);
        PropertyValuesHolder holder2 = PropertyValuesHolder.ofKeyframe("scaleY",keyframe00,keyframe01,keyframe011
                ,keyframe02,keyframe03, keyframe04);

        Keyframe keyframe10 = Keyframe.ofFloat(0,0f);
        Keyframe keyframe11 = Keyframe.ofFloat(0.1f,0f);   //500
        keyframe11.setInterpolator(new AccelerateInterpolator());
        Keyframe keyframe12 = Keyframe.ofFloat(0.2f,50f);  //1000
        Keyframe keyframe122 = Keyframe.ofFloat(0.8f,50f);  //4000
        keyframe122.setInterpolator(new AccelerateInterpolator());
        Keyframe keyframe13 = Keyframe.ofFloat(0.9f,0f);   //4500
        Keyframe keyframe14 = Keyframe.ofFloat(1f,0.0f);
        PropertyValuesHolder holder3 = PropertyValuesHolder.ofKeyframe("test",keyframe10,keyframe11
                ,keyframe12,keyframe122, keyframe13, keyframe14);
        

        final ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(fv, holder, holder2, holder3);
        animator.setDuration(5000);
        animator.setInterpolator(new AccelerateDecelerateInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                float scaleYValue = (float) animation.getAnimatedValue("test");
                //fv.setScaleX(scaleYValue);
                Drawable d = createDrawagle(100-scaleYValue);
                lv.setBackground(d);
                

            }
        });
        animator.start();
    }

修改形状可以使用BitmapShader,这是一个功能十分强大的函数,也可以使用setXfermode,这是一个比BitmapShader功能更强大的函数,可以使用他几乎可以得到任意图形,结合数学函数知识,我们可以动态绘制很多神奇的图形,

这是 一个应用setXfermode实现的半闭眼效果,也是上面用到的函数。

Drawable createDrawagle(float value){
        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        Paint p = new Paint();
        p.setColor(Color.WHITE);
        p.setAntiAlias(true);

        Canvas c = new Canvas(bitmap);
        Canvas c1 = new Canvas(bitmap2);

        c.drawCircle(50,50, 50, p);
        c1.drawRect(new RectF(0, 0, 100, 100), p);
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        //c.drawRect(new RectF(0, (100-value)/2, 100, ((100-value)/2)+value), p);
        //c.drawRect(new RectF(0, 0, 100, 50), p);
        c.drawBitmap(bitmap2, 0, value, p);
        BitmapDrawable drawable = new BitmapDrawable(getResources(), bitmap);
        return drawable;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值