仿某直播平台的点赞效果

现在的直播平台已经是多的不得了了,而给主播点赞的效果,也是各不相同,今天,我们来自定义一个点赞的效果!
先上效果:

这里写图片描述

当点击点赞按钮的时候,就会有不同颜色的心型从底部冒出,并按照不规则的路线运动,在运动过程中,伴随着各种动画!

好了,话不多说,直接上代码:

/**
 * Created by DELL on 2017/9/16.
 * Description : 花束点赞效果
 */

public class PraiseView extends RelativeLayout {

    private int[] drawables;
    private Context mContext;
    //图片的宽高
    private int mDrawableHeight;
    private int mDrawableWidth;

    //随机数
    private Random mRandom;

    public PraiseView(Context context) {
        this(context,null);
    }

    public PraiseView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public PraiseView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.mContext = context;
        //创建随机数 在后面的贝塞尔取点钟会用到
        mRandom = new Random();
        //初始化心形图片
        drawables = new int[]{R.drawable.pl_blue,R.drawable.pl_red,R.drawable.pl_yellow};

        //获取心形图片的宽高
        Drawable drawable = ContextCompat.getDrawable(context,drawables[0]);
        mDrawableHeight = drawable.getIntrinsicHeight();
        mDrawableWidth = drawable.getIntrinsicWidth();
    }

    //在屏幕底部添加心形图片
    public void addDrawables(){
        final ImageView imageView = new ImageView(mContext);
        imageView.setImageResource(drawables[mRandom.nextInt(drawables.length-1)]);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(ALIGN_PARENT_BOTTOM);
        params.addRule(CENTER_HORIZONTAL);
        imageView.setLayoutParams(params);
        addView(imageView);

        //创建并开启动画效果
        AnimatorSet animatorSet = getAnimator(imageView);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //在动画执行结束之后,移除该view
                removeView(imageView);
            }
        });
        animatorSet.start();
    }

    //创建动画

    /**
     * 刚开始做缩放和渐变动画  结束后开始做移动动画
     * @param imageView
     * @return
     */
    private AnimatorSet getAnimator(ImageView imageView){
        //缩放动画
        ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView,"scaleX",0.3f,1f);
        ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView,"scaleY",0.3f,1f);
        //渐变动画
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(imageView,"alpha",0.3f,1f);

        AnimatorSet set = new AnimatorSet();
        set.playTogether(scaleXAnimator,scaleYAnimator,alphaAnimator);
        set.setDuration(300);

        //创建平移动画并添加到set执行完成之后执行
        AnimatorSet wholeAnimator = new AnimatorSet();
        //按照顺序执行
        wholeAnimator.playSequentially(set,getBeizerAnimator(imageView));
        return wholeAnimator;
    }

    private ValueAnimator getBeizerAnimator(final ImageView imageView){
        //首先先确定需要用到的四个点
        //点0是在图片开始的中心点
        final PointF point0 = new PointF(getWidth()/2 - mDrawableWidth/2,getHeight() - mDrawableHeight);
        //点1 点2是贝塞尔曲线的控制点  需要控制的是,点2的高度要大于点1的高度
        PointF point1 = getPoint(1);
        PointF point2 = getPoint(2);
        PointF point3 = new PointF(mRandom.nextInt(getWidth()/2) - mDrawableWidth/2,0);
        BeizerEvalator beizerEvalator = new BeizerEvalator(point1,point2);
        ValueAnimator beizerAnimator = ObjectAnimator.ofObject(beizerEvalator,point0,point3);
        beizerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        beizerAnimator.setDuration(4000);
        beizerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //在运行过程中会调用该方法
                PointF pointF = (PointF) animation.getAnimatedValue();
                imageView.setX(pointF.x);
                imageView.setY(pointF.y);

                //设置移动过程中的渐变
                //首先获取当前的fraction
                float fraction = animation.getAnimatedFraction();
                imageView.setAlpha(1-fraction);
            }
        });
        return beizerAnimator;
    }

    private PointF getPoint(int i){
        return new PointF(mRandom.nextInt(getWidth())- mDrawableWidth,mRandom.nextInt(getHeight()/2) + (i-1)*getHeight()/2);
    }
}

然后,我们需要一个估值器,来确定在某一时刻,沿着贝塞尔曲线的路径的点(这边,其实只要套公式就可以了)

/**
 * Created by DELL on 2017/9/16.
 * Description : 贝塞尔运动轨迹估值器
 */

public class BeizerEvalator implements TypeEvaluator<PointF> {

    private PointF point1,point2;

    public BeizerEvalator(PointF point1,PointF point2){
        this.point1 = point1;
        this.point2 = point2;
    }

    //直接套用贝塞尔三阶公式
    @Override
    public PointF evaluate(float fraction, PointF point0, PointF point3) {

        PointF pointF = new PointF();

        pointF.x = point0.x*(1-fraction)*(1-fraction)*(1-fraction)
                + 3*point1.x*fraction*(1-fraction)*(1-fraction)
                + 3*point2.x*fraction*fraction*(1-fraction)
                + point3.x*fraction*fraction*fraction;

        pointF.y = point0.y*(1-fraction)*(1-fraction)*(1-fraction)
                + 3*point1.y*fraction*(1-fraction)*(1-fraction)
                + 3*point2.y*fraction*fraction*(1-fraction)
                + point3.y*fraction*fraction*fraction;

        return pointF;
    }
}

按照以往的风格,注释都加在代码中了,如果大家还发现了什么问题,请回复我,大家一起讨论下!

最后,再来看一次效果:
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值