待写

4.Android 抖音点赞动效完美实现 200行

2021-06-18  本文已影响0人  鹏城十八少

请问:简书怎么可以把代码格式调整?我贴出来换格式了。你们直接去Github下载工程!

效果分析:

可以基本分为两个部分,具体看实现

1.点击START ANIM按钮的时候,底部出现一个ImageView它的drawable是随机的,并伴着缩放和透明度的变化;

2.等第一步的动画执行完后开始向上移动,移动的轨迹是一个曲线,我们要用到贝塞尔曲线公式去不断的改变图片的位置。

效果实现:

1.自定义控件Releativielayout,绘制出爱心控件

2.移动是一个曲线:配合估值器+贝塞尔曲线

3.自定义估值器封装:贝塞尔估值器

4.贝塞尔曲线实现:三阶贝塞尔:4个点确定,有一个公式

p1和P2的确定点公式

p0 :起点可以确定

p1:比p0的y值大

p2 要比p1的y值大

p3:终点可以确定

整个曲线我们可以简单的理解为这个S路曲线,S也会有四个点:

1.P0最下面的这个起点,也就是我们刚刚添加进来最下方居中的这个点 ((mWidth - mDrawableWidth) / 2, mHeight- mDrawableHeight)

2.P1是下半部分抛物线的顶点,这里是随机;

3.P2是上半部分抛物线的顶点,这里也是随机;

4.P3是最上面位置的终点(mRandom.nextInt(mWidth), 0),也就是最上面的这个点;

5.t的范围是[0,1],我们确定这四个点之后就开始套公式了:

5.view通过改变x和y的值。x和y就是一个点,通过动画得到(估值器得到)。点通过贝塞尔曲线

图片设置x,y,alpha。

因为估值器里面的定义是一个点。

@Override

public PointFevaluate(float t, PointF p0, PointF p3) {

PointF pointF=new PointF();

    pointF.x=p0.x*(1-t)*(1-t)*(1-t)

+3*p1.x*t*(1-t)*(1-t)

+3*p2.x*t*(t)*(1-t)

+p3.x*t*t*t;

    pointF.y=p0.y*(1-t)*(1-t)*(1-t)

+3*p1.y*t*(1-t)*(1-t)

+3*p2.y*t*(t)*(1-t)

+p3.y*t*t*t;

    return pointF;

PointF pointF=(PointF) valueAnimator.getAnimatedValue();//这个返回值就是估值器的值

ValueAnimator  objectAnimator = ObjectAnimator.ofObject(new LoveTypeEvalutor(point1, point2), point0, point3);

objectAnimator.setDuration(2000);

objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

    public void onAnimationUpdate(ValueAnimator valueAnimator) {

Log.d("dddd","onAnimationUpdate");

        PointF pointF=(PointF) valueAnimator.getAnimatedValue();//这个返回值就是估值器的值

        float r=valueAnimator.getAnimatedFraction();//这个值

        imageView.setX(pointF.x);//setx:指的是谁

        imageView.setY(pointF.y);

        imageView.setAlpha(1-r+0.2f);

    }

});

先说一下这种效果都用到了哪些东西:

1.自定义View的一些基础;

2.随机数的使用;

3.插补器的使用;

4.属性动画的一些高级用法

5.贝塞尔曲线应用到属性动画

public class DouyinPraiseextends RelativeLayout {

Randomrandom;

    public DouyinPraise(Context context) {

this(context, null);

    }

public DouyinPraise(Context context, AttributeSet attrs) {

this(context, attrs, 0);

        random =new Random();

    }

public DouyinPraise(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

    }

private int width;

    private int height;

    private int imageWidth, imageHeight;

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        width = MeasureSpec.getSize(widthMeasureSpec);

        height = MeasureSpec.getSize(heightMeasureSpec);

    }

public void addImageView() {

RelativeLayout.LayoutParams layoutParams =new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

        layoutParams.addRule(ALIGN_PARENT_BOTTOM);

        layoutParams.addRule(CENTER_HORIZONTAL);

        ImageView imageView =new ImageView(getContext());//如何得到view,inlat。可以直接new

        imageView.setImageResource(R.mipmap.ic_launcher);//如何获取图片的宽高

        imageWidth = imageView.getWidth();

        imageHeight = imageView.getHeight();

        addView(imageView, layoutParams);

        AnimatorSet animatorSet = getObjectAnimator(imageView);

        animatorSet.start();

    }

private AnimatorSetgetObjectAnimator(ImageView view) {

AnimatorSet animatorSetAll =new AnimatorSet();

        AnimatorSet animatorSet =new AnimatorSet();

        ObjectAnimator objectAnimatorAlpha = ObjectAnimator.ofFloat(view, "alpha", 0.3f, 1.0f);

        ObjectAnimator objectAnimatorScalex = ObjectAnimator.ofFloat(view, "scaleX", 0.1f, 1.0f);

        ObjectAnimator objectAnimatorScaleY = ObjectAnimator.ofFloat(view, "scaleY", 0.1f, 1.0f);

        animatorSet.playTogether(objectAnimatorAlpha, objectAnimatorScalex, objectAnimatorScaleY);

        animatorSet.setDuration(500);

        animatorSetAll.playSequentially(animatorSet, getBziAnimation(view));//播放动画

        animatorSetAll.start();

        return animatorSet;

    }

/***

    * 三次方公式

    * @return

    */

    private AnimatorgetBziAnimation(ImageView imageView) {

PointF point0 =new PointF(width /2, height);

        PointF point1 =new PointF(new Random().nextInt(width), random.nextInt(height/2));

        PointF point2 =new PointF(new Random().nextInt(width), random.nextInt(height/2)+height/2);

        PointF point3 =new PointF(new Random().nextInt(width), 0);

        ValueAnimator  objectAnimator = ObjectAnimator.ofObject(new LoveTypeEvalutor(point1, point2), point0, point3);

        objectAnimator.setDuration(2000);

        objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

            public void onAnimationUpdate(ValueAnimator valueAnimator) {

Log.d("dddd","onAnimationUpdate");

                PointF pointF=(PointF) valueAnimator.getAnimatedValue();//这个返回值就是估值器的值

                float r=valueAnimator.getAnimatedFraction();//这个值

                imageView.setX(pointF.x);//setx:指的是谁

                imageView.setY(pointF.y);

                imageView.setAlpha(1-r+0.2f);

            }

});

        objectAnimator.addListener(new Animator.AnimatorListener() {

@Override

            public void onAnimationStart(Animator animator) {

}

@Override

            public void onAnimationEnd(Animator animator) {

removeView(imageView);

            }

@Override

            public void onAnimationCancel(Animator animator) {

}

@Override

            public void onAnimationRepeat(Animator animator) {

}

});

        return objectAnimator;

    }

public class LoveTypeEvalutorimplements TypeEvaluator {

private PointFp1,p2;

    public LoveTypeEvalutor(PointF p1, PointF p2) {

this.p1 = p1;

        this.p2 = p2;

    }

@Override

    public PointFevaluate(float t, PointF p0, PointF p3) {

PointF pointF=new PointF();

        pointF.x=p0.x*(1-t)*(1-t)*(1-t)

+3*p1.x*t*(1-t)*(1-t)

+3*p2.x*t*(t)*(1-t)

+p3.x*t*t*t;

        pointF.y=p0.y*(1-t)*(1-t)*(1-t)

+3*p1.y*t*(1-t)*(1-t)

+3*p2.y*t*(t)*(1-t)

+p3.y*t*t*t;

        return pointF;

    }

}

https://blog.csdn.net/qq_16624353/article/details/93376688

https://www.jianshu.com/p/2a830d089310

demo地址:https://github.com/pengcaihua123456/shennandadao

上一篇 下一篇

猜你喜欢

热点阅读