仿直播点赞动画

来源:互联网 发布:win7打印机无usb端口 编辑:程序博客网 时间:2024/05/21 17:31

前一段时间感觉直播很火,因此我就下了七八个直播软件去看了,不要问我为啥下这么多,我会告诉你我想看看哪个平台的妹子颜值高吗,好吧最终喜欢上看映客的一个妹子。妹子歌唱的很好听可惜屌丝的我涮不起礼物,只能在屏幕下方狂点赞了。好了这次当然不是讨论直播平台的妹子,而是看下直播软件点赞的效果怎样实现的。
说一下思想吧,首先利用属性动画的放大效果让生成的图片不至于太突兀的显示,接着让生成的图片沿着三阶贝塞尔曲线的轨迹去移动,在移动的过程中逐渐设置图片的透明效果至0,最后在动画结束的时候remove掉新生成的图片。

下面看下效果图吧
这里写图片描述

效果就是这么个效果,下面看具体实现吧

首先看下布局文件

<RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.jh.mymathsintext.MainActivity">    <android.support.v7.widget.Toolbar        android:id="@+id/toolbar"        android:layout_width="match_parent"        android:layout_height="?actionBarSize"        android:background="@color/colorPrimary"        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"        app:title="@string/app_name">    </android.support.v7.widget.Toolbar>    <com.jh.mymathsintext.MyRelative        android:id="@+id/rela"        android:layout_width="200dp"        android:layout_height="match_parent"        android:layout_centerHorizontal="true"        android:layout_marginBottom="100dp"        android:layout_below="@id/toolbar"        android:gravity="bottom|center_horizontal">    </com.jh.mymathsintext.MyRelative>    <ImageView        android:id="@+id/img"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="@drawable/pl_blue"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="50dp"/></RelativeLayout>

布局文件没什么好讲的,接着看下具体实现,先把整体代码贴出来在分步细讲

public class MyRelative extends RelativeLayout{    private int []drawable={R.drawable.pl_blue,R.drawable.pl_red,R.drawable.pl_yellow};    private  LayoutParams params;    private Random random=new Random();    private int height,width;    public MyRelative(Context context) {        super(context);        init();    }    public MyRelative(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public MyRelative(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    /**     * 获取图片的大小     */    public void init(){        BitmapFactory.Options options=new BitmapFactory.Options();        options.inJustDecodeBounds=true;        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.pl_red,options);        width=options.outWidth;        height=options.outHeight;//        width=ContextCompat.getDrawable(getContext(),R.drawable.pl_red).getIntrinsicWidth();//        height=ContextCompat.getDrawable(getContext(),R.drawable.pl_red).getIntrinsicHeight();        params=new LayoutParams(width, height);    }    /**     * 生成图片,并设置动画     */    public void addView(){        final ImageView imageView=new ImageView(getContext());        imageView.setLayoutParams(params);        imageView.setBackgroundResource(drawable[random.nextInt(3)]);        addView(imageView);        AnimatorSet set=getAnimation(imageView);//属性动画控制放大效果        ValueAnimator valueAnimator=setPoint(imageView);//控制移动        AnimatorSet animatorSet=new AnimatorSet();        animatorSet.playSequentially(set,valueAnimator);//设置属性动画按顺序执行        animatorSet.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);                removeView(imageView);            }        });        animatorSet.start();    }    /**     * 属性动画控制放大效果     * @param imageView     * @return     */    public AnimatorSet getAnimation(ImageView imageView){        ObjectAnimator objectAnimator1=ObjectAnimator.ofFloat(imageView,SCALE_X,0f,1f);        ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(imageView,SCALE_Y,0f,1f);        AnimatorSet animatorSet=new AnimatorSet();        animatorSet.playTogether(objectAnimator1,objectAnimator2);//控制动画一起执行        animatorSet.setDuration(500);        return animatorSet;    }    /**     * 创建贝塞尔轨迹并让图片沿着贝塞尔轨迹运行     * @param imageView     * @return     */    public ValueAnimator setPoint(final View imageView){        MyPoint myPoint=new MyPoint(getPoint(2),getPoint(1));        ValueAnimator valueAnimator=ValueAnimator.ofObject(myPoint,new PointF((this.getWidth()-width)/2,this.getHeight()-height),                new PointF(random.nextInt(getWidth()),0));        valueAnimator.setDuration(2000);        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                PointF pointF= (PointF) animation.getAnimatedValue();                Log.i("tag","dfdgdfadfsdsdd"+pointF.x);                imageView.setX(pointF.x);                imageView.setY(pointF.y);                imageView.setAlpha(1-animation.getAnimatedFraction());            }        });        return valueAnimator;    }    /**     * 随机生成点     * @param height     * @return     */    public PointF getPoint(int height){        PointF pointF=new PointF();        pointF.x=random.nextInt(getWidth()-50);        pointF.y=random.nextInt(getHeight()-50)/height;        return pointF;    }}

首先需要获取一下图片的大小然后设置给新创建的imageview

 /**     * 获取图片的大小     */    public void init(){        BitmapFactory.Options options=new BitmapFactory.Options();        options.inJustDecodeBounds=true;        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.pl_red,options);        width=options.outWidth;        height=options.outHeight;//        width=ContextCompat.getDrawable(getContext(),R.drawable.pl_red).getIntrinsicWidth();//        height=ContextCompat.getDrawable(getContext(),R.drawable.pl_red).getIntrinsicHeight();        params=new LayoutParams(width, height);    }

然后就是给新创建的imageview设置放大动画了,这里利用属性动画实现

/**     * 属性动画控制放大效果     * @param imageView     * @return     */    public AnimatorSet getAnimation(ImageView imageView){        ObjectAnimator objectAnimator1=ObjectAnimator.ofFloat(imageView,SCALE_X,0f,1f);        ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(imageView,SCALE_Y,0f,1f);        AnimatorSet animatorSet=new AnimatorSet();        animatorSet.playTogether(objectAnimator1,objectAnimator2);//控制动画一起执行        animatorSet.setDuration(500);        return animatorSet;    }

接下来就是要让新生成的imageview实现沿着三阶贝塞尔曲线轨迹去移动了,重点是获取三阶贝塞尔曲线的轨迹坐标,这个可以利用实现TypeEvaluator接口和PointF实现。这是会重写TypeEvaluator接口里的evaluate()方法,看下方法实现吧

    @Override    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {        float timeDel=1-fraction;        PointF pointF=new PointF();        //三阶贝塞尔曲线公式        pointF.x=timeDel*timeDel*timeDel*startValue.x+3*pointF1.x*timeDel*timeDel*fraction+3*pointF2.x*fraction*fraction*timeDel+                endValue.x*fraction*fraction*fraction;        pointF.y=timeDel*timeDel*timeDel*startValue.y+3*pointF1.y*timeDel*timeDel*fraction+3*pointF2.y*fraction*fraction*timeDel+                endValue.y*fraction*fraction*fraction;        return pointF;    }

对就是在上述方法里实现获取三阶贝塞尔曲线轨迹坐标,先看下贝塞尔曲线的公式

这里写图片描述

三阶贝塞尔曲线公式如上,因为evaluate()方法里有起始点和终点,只需要在创建两个点就可以了,为了让每一个生成的imageview运行轨迹大致不相同,我们可以随机生成这两个点,代码如下所示

 /**     * 随机生成点     * @param height     * @return     */    public PointF getPoint(int height){        PointF pointF=new PointF();        pointF.x=random.nextInt(getWidth()-50);        pointF.y=random.nextInt(getHeight()-50)/height;        return pointF;    }

接下来需要做的事情就是将轨迹坐标赋给imageview,代码如下

 /**     * 创建贝塞尔轨迹并让图片沿着贝塞尔轨迹运行     * @param imageView     * @return     */    public ValueAnimator setPoint(final View imageView){        MyPoint myPoint=new MyPoint(getPoint(2),getPoint(1));        ValueAnimator valueAnimator=ValueAnimator.ofObject(myPoint,new PointF((this.getWidth()-width)/2,this.getHeight()-height),                new PointF(random.nextInt(getWidth()),0));        valueAnimator.setDuration(2000);        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                PointF pointF= (PointF) animation.getAnimatedValue();                Log.i("tag","dfdgdfadfsdsdd"+pointF.x);                imageView.setX(pointF.x);                imageView.setY(pointF.y);                imageView.setAlpha(1-animation.getAnimatedFraction());            }        });        return valueAnimator;    }

然后需要做的就是将放大动画和轨迹动画设置给imageview去实现即可,

 /**     * 生成图片,并设置动画     */    public void addView(){        final ImageView imageView=new ImageView(getContext());        imageView.setLayoutParams(params);        imageView.setBackgroundResource(drawable[random.nextInt(3)]);        addView(imageView);        AnimatorSet set=getAnimation(imageView);//属性动画控制放大效果        ValueAnimator valueAnimator=setPoint(imageView);//控制移动        AnimatorSet animatorSet=new AnimatorSet();        animatorSet.playSequentially(set,valueAnimator);//设置属性动画按顺序执行        animatorSet.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);                removeView(imageView);            }        });        animatorSet.start();    }

注意的一点是在动画结束的时候最好将生成的imageview给移除掉,到此为止点赞效果就做出来了,别拦我,我要去跟女神表白了

0 0
原创粉丝点击