自定义的一个粘性的指示器。
先看看效果。效果赞不赞因人而异,想更酷一些的话,可以花时间实现一下,这里就是想给大家分享一下实现的思路。
1.继承View。获取、计算 一些必要的数据。如:padding,view大小,圆点大小颜色,圆圈大小颜色,动画时间,圆点数量等。
2.获取、保存每个圆圈 的位置坐标。
3..放开选择index公共方法。调用此方法后,根据当前index和将要到达的index,获取到两个圆圈的位置坐标。启动圆圈粘性动画和圆点移动动画。
4.用ValueAnimator 从0到1,的百分百数据。根据两个点之间的总距离,算出当前位置坐标,形变程度等数据。draw出来(会画圆点和所有的圆圈)。
5.在圆点到位后,启动圆点形变复原动画。
6.动画结束后,即时改变当前index等数据。
注意点就是在动画执行完之前,用户再次选择。这个在用户选择之前判断动画是否完成,如果没完成,调用onCancel方法,onCancel中将数据即时改变。
下图可以更好的理解代码中的数据:
下面是自定义的view代码:
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
public class BezierLinearPointsView extends View {
// 绘制圆形贝塞尔曲线控制点的位置
private static final float C = 0.551915024494f;
private int mViewWidth = 0, mViewHeight = 0;
private int mViewLeftPadding = 0, mViewRightPadding = 0,
mViewTopPadding = 0, mViewButtomPadding = 0;
// 点数,默认为3
private int mCount = 3;
// 选中小点颜色
private int mSelectedColor = Color.GREEN;
// 未选中小点颜色
private int mUnSelectedColor = Color.YELLOW;
// 小点大小
private int mPointSize = 50;
// 画笔宽度
private int mPaintStrokeWidth = 6;
// 位移动画时间
private long mDuration = 500;
// 恢复动画时间
private long mDurationRe = 200;
// 大小抖动动画时间
private long mDurationSize = 500;
// 是否循环
private boolean isLooper = false;
// 外发光宽度 是 线条宽度的几倍
private int mBlurRadio = 2;
// 两个圆的paint
private Paint mUnselectedPaint, mSelectedPaint;
private Path mPath = new Path();
// 存放未选中点的 位置数据
private ArrayList<int[]> mUnselectedPoints = new ArrayList<int[]>();
// 当前位置
private int mCurrentIndex = 0, mToIndex = 0;
// 两个圆之间圆心距离
private int mDis = 20;
// 当前选中点的位置
private int[] mCurrentPointCenter;
// 将要选中点的位置
private int[] mToPointCenter;
// 动画执行进度,用来控制圆的形变程度
private float mPercent = 0f;
// 反弹动画执行进度,用来控制圆的复原形变程度
private float mRePercent = 0f;
// 圆圈从未选中到选中抖动动画程度
private float mSizePercent = 1f;
// 圆形的控制点与数据点的差值
private float mDifference;
// 顺时针记录绘制圆形的四个数据点
private float[] mData = new float[8];
// 顺时针记录绘制圆形的八个控制点
private float[] mCtrl = new float[16];
// 来标识形变 恢复的时候是改动哪个点。0:两点相同,不变。1:index增加恢复,更改的是圆的左点。-1:index减少恢复,更改圆右点
private int isIndexInCreate = 0;
// 位移动画
private ValueAnimator va;
// 恢复动画
private ValueAnimator vaRe;
// 圆圈从 选中到不选中,粘性动画
private ValueAnimator vaSize;
public BezierLinearPointsView(Context context) {
super(context);
init(context, null);
}
public BezierLinearPointsView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public BezierLinearPointsView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
// public BezierLinearPointsView(Context context, AttributeSet attrs,
// int defStyleAttr, int defStyleRes) {
// super(context, attrs, defStyleAttr, defStyleRes);
// init(context, attrs);
// }
/**
* 初始化一些