public class MyView extends View {
private Point controlPoint = new Point(200, 200); //控制点坐标
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(10);//设置画笔风格
Path path = new Path();
path.moveTo(100, 500);
path.quadTo(controlPoint.x, controlPoint.y, 700, 500);
//绘制路径
canvas.drawPath(path, paint);
//绘制辅助点
canvas.drawPoint(controlPoint.x,controlPoint.y,paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
controlPoint.x = (int) event.getX();
controlPoint.y = (int) event.getY();
invalidate();//得到手触摸屏幕的坐标
break;
}
return true;
}
}
public class MyView1 extends View {
private Point controlPointOne = new Point(200, 200);
private Point controlPointTwo = new Point(500, 200);
private boolean isControlPointTwo ;
private Paint paintBezier;
private Paint paintLine;
public MyView1(Context context) {
this(context, null);
}
public MyView1(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paintBezier = new Paint();
paintBezier.setStyle(Paint.Style.STROKE);
paintBezier.setColor(Color.BLACK);
paintBezier.setStrokeWidth(10);
paintLine = new Paint();
paintLine.setStyle(Paint.Style.STROKE);
paintLine.setColor(Color.RED);
paintLine.setStrokeWidth(3);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Path path = new Path();
path.moveTo(100, 500);
path.cubicTo(controlPointOne.x, controlPointOne.y,controlPointTwo.x, controlPointTwo.y, 900, 500);
//绘制路径
canvas.drawPath(path, paintBezier);
//绘制辅助点
canvas.drawPoint(controlPointOne.x, controlPointOne.y, paintBezier);
canvas.drawPoint(controlPointTwo.x, controlPointTwo.y, paintBezier);
//绘制连线
// canvas.drawLine(100, 500, controlPointOne.x, controlPointOne.y, paintLine);
// canvas.drawLine(900, 500, controlPointOne.x, controlPointOne.y, paintLine);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (isControlPointTwo){
controlPointOne.x = (int) event.getX();
controlPointOne.y = (int) event.getY();
}else {
controlPointTwo.x = (int) event.getX();
controlPointTwo.y = (int) event.getY();
}
invalidate();
break;
}
return true;
}
public boolean isControlPointTwo() {
return isControlPointTwo;
}
public void setControlPointTwo(boolean controlPointTwo) {
isControlPointTwo = controlPointTwo;
}
}
public class LikeStar extends ViewGroup {
private List<Drawable> mStarDrawable;
private List<Interpolator> mInterpolators;
private int mWidth;
private int mHeight;
//定义贝塞尔曲线的数据点和两个控制点
private PointF mStartPoint, mEndPoint, mControllPointOne, mControllPointTwo;
private Random random = new Random();
public LikeStar(Context context) {
this(context, null);
}
public LikeStar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LikeStar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(final Context context) {
mStarDrawable = new ArrayList<>();
mInterpolators = new ArrayList<>();
mStartPoint = new PointF();
mEndPoint = new PointF();
mControllPointOne = new PointF();
mControllPointTwo = new PointF();
//初始化图片资源
mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_red));
mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_blue));
mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_yellow));
mStarDrawable.add(getResources().getDrawable(R.mipmap.heart_green));
//初始化插补器
mInterpolators.add(new LinearInterpolator());
mInterpolators.add(new AccelerateDecelerateInterpolator());
mInterpolators.add(new AccelerateInterpolator());
mInterpolators.add(new DecelerateInterpolator());
ImageView image_heard = new ImageView(context);
image_heard.setImageDrawable(mStarDrawable.get(0));
image_heard.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
image_heard.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//点击之后开始动画,添加红心到布局文件并开始动画
final ImageView image_random = new ImageView(context);
image_random.setImageDrawable(mStarDrawable.get(random.nextInt(4)));
image_random.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
addView(image_random);
invalidate();
//开始做动画效果
PointF endPointRandom = new PointF(random.nextInt(mWidth), mEndPoint.y);
// BezierTypeEvaluator bezierTypeEvaluator = new BezierTypeEvaluator(mControllPointOne, mControllPointTwo);
BezierTypeEvaluator bezierTypeEvaluator = new BezierTypeEvaluator(new PointF( random.nextInt(mWidth ),random.nextInt(mHeight)), new PointF( random.nextInt(mWidth),random.nextInt(mHeight)));
ValueAnimator valueAnimator = ValueAnimator.ofObject(bezierTypeEvaluator, mStartPoint, endPointRandom);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
image_random.setX(pointF.x);
image_random.setY(pointF.y);
}
});
valueAnimator.setDuration(2000);
valueAnimator.start();
}
});
addView(image_heard);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
// 初始化各个点
//借用第一个子view控件中的宽高
View child = getChildAt(0);
int childW = child.getMeasuredWidth();
int childH = child.getMeasuredHeight();
mStartPoint.x = (mWidth - childW) / 2;
mStartPoint.y = mHeight - childH;
mEndPoint.x = (mWidth - childW) / 2;
mEndPoint.y = 0 - childH;
mControllPointOne.x = random.nextInt(mWidth / 2);
mControllPointOne.y = random.nextInt(mHeight / 2) + mHeight / 2;
mControllPointTwo.x = random.nextInt(mWidth / 2) + mWidth / 2;
mControllPointTwo.y = random.nextInt(mHeight / 2);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
//获取view的宽高测量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//保存测量高度
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("zhangyubin", "l:" + l + ",t:" + t + ",r:" + r + ",b:" + b);
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int childW = child.getMeasuredWidth();
int childH = child.getMeasuredHeight();
child.layout((mWidth - childW) / 2, (mHeight - childH), (mWidth - childW) / 2 + childW, mHeight);
}
}
// /**
// * 开始动画
// */
//向外提供方法,用于点击事件触发动画发生
public void startRunning() {
BezierTypeEvaluator bezierTypeEvaluator = new BezierTypeEvaluator(mControllPointOne, mControllPointTwo);
ValueAnimator valueAnimator = ValueAnimator.ofObject(bezierTypeEvaluator, mStartPoint, mEndPoint);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
getChildAt(0).setX(pointF.x);
getChildAt(0).setY(pointF.y);
}
});
valueAnimator.setDuration(3000);
valueAnimator.start();
}
public class BezierTypeEvaluator implements TypeEvaluator<PointF> {
private PointF mControllPoint1, mControllPoint2;
public BezierTypeEvaluator(PointF mControllPointOne, PointF mControllPointTwo) {
mControllPoint1 = mControllPointOne;
mControllPoint2 = mControllPointTwo;
}
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF pointCur = new PointF();
pointCur.x = mStartPoint.x * (1 - fraction) * (1 - fraction) * (1 - fraction) + 3
* mControllPoint1.x * fraction * (1 - fraction) * (1 - fraction) + 3
* mControllPoint2.x * (1 - fraction) * fraction * fraction + endValue.x * fraction * fraction * fraction;// 实时计算最新的点X坐标
pointCur.y = mStartPoint.y * (1 - fraction) * (1 - fraction) * (1 - fraction) + 3
* mControllPoint1.y * fraction * (1 - fraction) * (1 - fraction) + 3
* mControllPoint2.y * (1 - fraction) * fraction * fraction + endValue.y * fraction * fraction * fraction;// 实时计算最新的点Y坐标
return pointCur;
}
}
}