前言
又到年底了,有好工作的开心过年,像我这样的准备换工作的萌新只有忧虑中过年,因为已经裸辞,好在今年还存了点钱过年回来找工作还是可以苟一段时间的。所以闲下来便随便写写东西,打发时间同时也可以增加点简历的丰富度。先看效果图吧
效果图
实现原理
实现原理很简单就是添加一个View的属性动画,动画效果用贝塞尔二阶曲线实现
贝塞尔曲线公式如下
所以只需要套入公式便可以使用。
属性动画中有两个重点,有一个是setInterpolator(),还有一个是setEvaluator()。前者是控制速率,也就是先快后慢还是匀速还是什么等等,而后者则是控制如何变化,比如直线还是曲线。很明显我们此功能要用后者的方法。使用方式如下
valueAnimator.setEvaluator(new TypeEvaluator() {
@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的父布局
到此本以为大功告成,结果没想到又出了问题
点击位置和动画位置不同。这个问题为纠结了半天,最后感觉应该是获取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() {
@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;
}
}
结尾
年底了祝大家技术更上一层楼,有工作的甚至加薪,没工作找工作的找到满意的工作
新年快乐!