仿酷狗添加音乐动画

作者: _独爱夜色 | 来源:发表于2018-02-01 11:24 被阅读0次

    前言

    又到年底了,有好工作的开心过年,像我这样的准备换工作的萌新只有忧虑中过年,因为已经裸辞,好在今年还存了点钱过年回来找工作还是可以苟一段时间的。所以闲下来便随便写写东西,打发时间同时也可以增加点简历的丰富度。先看效果图吧

    效果图

    2018-02-01_10_51_25.gif

    实现原理

    实现原理很简单就是添加一个View的属性动画,动画效果用贝塞尔二阶曲线实现
    贝塞尔曲线公式如下


    Bézier .jpg

    所以只需要套入公式便可以使用。
    属性动画中有两个重点,有一个是setInterpolator(),还有一个是setEvaluator()。前者是控制速率,也就是先快后慢还是匀速还是什么等等,而后者则是控制如何变化,比如直线还是曲线。很明显我们此功能要用后者的方法。使用方式如下

     valueAnimator.setEvaluator(new TypeEvaluator<Point>() {
                @Override
                public Point evaluate(float t, Point startValue, Point endValue) {
                    Point controllPoint = new Point(endX, startY);//贝塞尔曲线控制点
                    int x = (int) ((1 - t) * (1 - t) * startValue.x + 2 * t * (1 - t) * controllPoint.x + t * t * endValue.x);//根据公式算出X
                    int y = (int) ((1 - t) * (1 - t) * startValue.y + 2 * t * (1 - t) * controllPoint.y + t * t * endValue.y);//根据公式算出Y
                    return new Point(x, y);
                }
            });
    

    接下来是给当前View赋值

      valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Point point = (Point) animation.getAnimatedValue();
                    setX(point.x);
                    setY(point.y);
                    setRotation(point.x * 2);
                }
            });
    

    这样便完成了一个动画
    但在ListView使用中发现存在很多问题
    首先是如果在Item的布局中添加此View那么View的显示范围只有Item的高度,也就是说超过高度后就看不见了,很明显这不是我们要的效果,所以必须将此View添加到ListView的上层布局中

     KuGouView kuGouView = new KuGouView(context);
     kuGouView.setImageResource(R.mipmap.add);
     viewGroup.addView(kuGouView);//ViewGroup为ListView的父布局
    

    到此本以为大功告成,结果没想到又出了问题


    2018-02-01_11_13_47.gif

    点击位置和动画位置不同。这个问题为纠结了半天,最后感觉应该是获取View位置的方法的问。

      int location[] = new int[2];
      v.getLocationInWindow(location);
    

    看了这个方法我就像是否与Title,Actionbar有关,仔细看下发现偏移的位置和Title高度差不多。于是网上各种搜索终于搜到一篇
    https://www.cnblogs.com/wjtaigwh/p/6689684.html
    其中意思是

    所以getLocationInWindow方法获取的是状态栏+contentView的大小,而不是我们以为的contentView的大小,知道了这里我们基本上就知道怎么解决这个问题了,只需要减去这个高度就可以了,我们可以直接减去mRecyclerView的Y坐标即可
    我这里的写法是

      int distance[] = new int[2];
      listView.getLocationInWindow(distance);
      kuGouView.startAnimation(location[0], location[1] - distance[1], rlt.getMeasuredWidth() / 2, play[1]);
    

    PS:其实我遇到的问题这里面都有,而且比我写的详细的多,本人只是大概的写一下自己的方式,如果想了解更多可以去这个地址看,感谢这位大神。

    最后GitHub就不给了就一个View页面的问题 给个代码吧

    package com.ren.framework.kugoulistview.widget;
    
    import android.animation.Animator;
    import android.animation.ObjectAnimator;
    import android.animation.TypeEvaluator;
    import android.animation.ValueAnimator;
    import android.content.Context;
    import android.graphics.Point;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.ViewTreeObserver;
    import android.view.animation.LinearInterpolator;
    import android.widget.ImageView;
    
    /**
     * Created by Ren on 2018/1/31.
     * TODO
     */
    
    public class KuGouView extends ImageView {
    
    
        public KuGouView(Context context) {
            super(context);
            init();
        }
    
        public KuGouView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public KuGouView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
        }
    
        public void startAnimation(int endX, int endY) {
            startAnimation((int) getX(), (int) getY(), endX, endY);
        }
    
        public void startAnimation(int startX, final int startY, final int endX, int endY) {
            ValueAnimator valueAnimator = new ValueAnimator();
            valueAnimator.setObjectValues(new Point(startX, startY), new Point(endX, endY));
            valueAnimator.setDuration(600);
            valueAnimator.setInterpolator(new LinearInterpolator());
            valueAnimator.setEvaluator(new TypeEvaluator<Point>() {
                @Override
                public Point evaluate(float t, Point startValue, Point endValue) {
                    Point controllPoint = new Point(endX, startY);//贝塞尔曲线控制点
                    int x = (int) ((1 - t) * (1 - t) * startValue.x + 2 * t * (1 - t) * controllPoint.x + t * t * endValue.x);//根据公式算出X
                    int y = (int) ((1 - t) * (1 - t) * startValue.y + 2 * t * (1 - t) * controllPoint.y + t * t * endValue.y);//根据公式算出Y
                    return new Point(x, y);
                }
            });
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Point point = (Point) animation.getAnimatedValue();
                    setX(point.x);
                    setY(point.y);
                    setRotation(point.x * 2);
                }
            });
            valueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    if (listener != null) {
                        listener.onStart(animation);
                    }
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (listener != null)
                        listener.onComplete(animation);
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
    
                }
            });
            valueAnimator.start();
        }
    
        public interface AnimationListener {
            void onStart(Animator animation);
    
            void onComplete(Animator animation);
    
        }
    
        private AnimationListener listener;
    
        public void setAnimationListener(AnimationListener listener) {
            this.listener = listener;
        }
    }
    
    

    结尾

    年底了祝大家技术更上一层楼,有工作的甚至加薪,没工作找工作的找到满意的工作
    新年快乐!

    相关文章

      网友评论

        本文标题:仿酷狗添加音乐动画

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