美文网首页
实现爱心满天飞的效果

实现爱心满天飞的效果

作者: L_Xian | 来源:发表于2016-05-30 10:23 被阅读200次

    最近需要完成这样的一个效果:

    sdasd.gif

    看上去就是动画跟贝塞尔曲线的组合,但是因为动画不熟悉,所以比较难以实现,这里的代码是摘取至 hcc大神的分享

    LoveLikeLayout:

    public class LoveLikeLayout extends RelativeLayout {
    
        //线性插值器
        private Interpolator line = new LinearInterpolator();
    
        //加速插值器
        private Interpolator acc = new AccelerateInterpolator();
    
        //减速插值器
        private Interpolator dce = new DecelerateInterpolator();
    
        //先加速后减速插值器
        private Interpolator accdec = new AccelerateDecelerateInterpolator();
    
        //插值器数组
        private Interpolator[] interpolators;
    
        //随机数
        private Random mRandom = new Random();
    
        //爱心图片数组
        private Drawable[] drawables;
    
        //爱心图片的高度
        private int drawableHeight;
    
        //爱心图片的宽度
        private int drawableWidth;
    
        //参数值
        private LayoutParams layoutParams;
    
        //layout高度
        private int measuredHeight;
    
        //layout宽度
        private int measuredWidth;
    
        public LoveLikeLayout(Context context) {
            this(context, null);
        }
    
        public LoveLikeLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public LoveLikeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        /**
         * 初始化
         */
        private void init() {
            //初始化爱心图片
            drawables = new Drawable[3];
            Drawable red = getResources().getDrawable(R.drawable.pl_red);
            Drawable yellow = getResources().getDrawable(R.drawable.pl_yellow);
            Drawable blue = getResources().getDrawable(R.drawable.pl_blue);
            drawables[0] = red;
            drawables[1] = yellow;
            drawables[2] = blue;
    
            //获取爱心的宽高
            drawableHeight = red.getIntrinsicHeight();
            drawableWidth = red.getIntrinsicWidth();
    
            //设置爱心的显示位置
            layoutParams = new LayoutParams(drawableWidth, drawableHeight);
            layoutParams.addRule(CENTER_HORIZONTAL, TRUE);
            layoutParams.addRule(ALIGN_PARENT_BOTTOM, TRUE);
    
            //初始化动画插值器
            interpolators = new Interpolator[4];
            interpolators[0] = line;
            interpolators[1] = acc;
            interpolators[2] = dce;
            interpolators[3] = accdec;
        }
    
        /**
         * 测量layout的宽高
         * 用于计算爱心的显示位置
         *
         * @param widthMeasureSpec
         * @param heightMeasureSpec
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            measuredHeight = getMeasuredHeight();
            measuredWidth = getMeasuredWidth();
        }
    
        /**
         * 显示爱心
         */
        public void addLove() {
            final ImageView imageView = new ImageView(getContext());
            //随机生成爱心颜色
            imageView.setImageDrawable(drawables[mRandom.nextInt(3)]);
            imageView.setLayoutParams(layoutParams);
    
            addView(imageView);
            Animator animtor = getAnimtor(imageView);
            animtor.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    removeView(imageView);
                    super.onAnimationEnd(animation);
                }
            });
            animtor.start();
        }
    
    
        /**
         * 爱心的显示和运行轨迹动画组合实现
         *
         * @param target
         * @return
         */
        private Animator getAnimtor(View target) {
            AnimatorSet enterAnimtorSet = getEnterAnimtorSet(target);
            ValueAnimator bezierAnimtor = getBezierAnimtor(target);
    
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.playSequentially(enterAnimtorSet);
            animatorSet.playSequentially(enterAnimtorSet, bezierAnimtor);
            animatorSet.setInterpolator(interpolators[mRandom.nextInt(4)]);
            animatorSet.setTarget(target);
    
            return animatorSet;
        }
    
    
        /**
         * 爱心的显示动画实现
         *
         * @param target
         * @return
         */
        private AnimatorSet getEnterAnimtorSet(View target) {
            //爱心的3中动画组合 透明度 x,y轴的缩放
            ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f);
            ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 0.2f, 1f);
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.2f, 1f);
    
            //组合动画
            AnimatorSet set = new AnimatorSet();
            set.setDuration(500);
            set.setInterpolator(new LinearInterpolator());
            set.playTogether(alpha, scaleX, scaleY);
            set.setTarget(target);
    
            return set;
        }
    
    
        /**
         * 爱心运动轨迹的动画实现
         *
         * @param target
         * @return
         */
        private ValueAnimator getBezierAnimtor(final View target) {
            BezierEvaluator evaluator = new BezierEvaluator(getPoint(2), getPoint(1));
    
            ValueAnimator animator = ValueAnimator.ofObject(evaluator,
                    new PointF((measuredWidth - drawableWidth) / 2, measuredHeight - drawableHeight),
                    new PointF(mRandom.nextInt(getWidth()), 0));
    
    
            animator.setDuration(3000);
            animator.setTarget(target);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    //获取贝塞尔曲线的运动轨迹 让爱心跟随着移动
                    PointF animatedValue = (PointF) valueAnimator.getAnimatedValue();
                    target.setX(animatedValue.x);
                    target.setY(animatedValue.y);
                    //增加透明度的变化
                    target.setAlpha(1 - valueAnimator.getAnimatedFraction());
                }
            });
    
            return animator;
        }
    
        /**
         * 获取中间的两个点
         *
         * @return
         */
        private PointF getPoint(int scale) {
            PointF pointF = new PointF();
            pointF.x = mRandom.nextInt((measuredWidth - 100));
            pointF.y = mRandom.nextInt((measuredHeight - 100)) / scale;
            return pointF;
        }
    }
    
    

    BezierEvaluator:

    public class BezierEvaluator implements TypeEvaluator<PointF> {
    
    
        private PointF pointF1;
        private PointF pointF2;
    
        public BezierEvaluator(PointF pointF1, PointF pointF2) {
            this.pointF1 = pointF1;
            this.pointF2 = pointF2;
        }
    
        @Override
        public PointF evaluate(float time, PointF startValue, PointF endValue) {
    
            float timeLeft = 1.0f - time;
            PointF point = new PointF();//结果
    
            point.x = timeLeft * timeLeft * timeLeft * (startValue.x)
                    + 3 * timeLeft * timeLeft * time * (pointF1.x)
                    + 3 * timeLeft * time * time * (pointF2.x)
                    + time * time * time * (endValue.x);
    
            point.y = timeLeft * timeLeft * timeLeft * (startValue.y)
                    + 3 * timeLeft * timeLeft * time * (pointF1.y)
                    + 3 * timeLeft * time * time * (pointF2.y)
                    + time * time * time * (endValue.y);
            return point;
        }
    }
    
    

    用法:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:background="#80000000"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
    
        <com.stay4it.widgets.ui.LoveLikeLayout
            android:id="@+id/id_LoveLikeLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    
        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="点击" />
    </LinearLayout>
    
    
    public class LoveActivity extends AppCompatActivity {
        private LoveLikeLayout mLoveLikeLayout;
        private Button btn;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_love);
            mLoveLikeLayout = (LoveLikeLayout) findViewById(R.id.id_LoveLikeLayout);
            btn = (Button) findViewById(R.id.btn);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mLoveLikeLayout.addLove();
                }
            });
        }
    

    先把代码摘录下来,后面再研究。。

    相关文章

      网友评论

          本文标题:实现爱心满天飞的效果

          本文链接:https://www.haomeiwen.com/subject/iwnqdttx.html