package com.test.myapplication;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
public class MyView extends View {
private float mHeight;
private float mWidth;
private float radius = 40f;
private float currentRadius;
private Paint mPaint;
private PointF mStickCenter;
private PointF mDragCenter;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mHeight = getHeight();
mWidth = getWidth();
currentRadius = radius;
mStickCenter = new PointF(mWidth / 2, mHeight / 2);
mDragCenter = new PointF(mWidth / 2, mHeight / 2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float xdelta = mDragCenter.x - mStickCenter.x;
float ydelta = mDragCenter.y - mStickCenter.y;
float distance = (float) Math.sqrt(xdelta * xdelta + ydelta * ydelta);
//拖拽圆
canvas.drawCircle(mDragCenter.x, mDragCenter.y, radius, mPaint);
if (distance != 0) {
currentRadius = radius * (1 - Math.min(distance / 3, 100) / 100);
if (currentRadius < 5) {
currentRadius = 5;
}
//变化圆
canvas.drawCircle(mStickCenter.x, mStickCenter.y, currentRadius, mPaint);
float cos = ydelta / distance;
float sin = xdelta / distance;
//变化圆切点1
PointF stick1 = new PointF();
stick1.x = mStickCenter.x - currentRadius * cos;
stick1.y = mStickCenter.y + currentRadius * sin;
//变化圆切点2
PointF stick2 = new PointF();
stick2.x = mStickCenter.x + currentRadius * cos;
stick2.y = mStickCenter.y - currentRadius * sin;
//拖拽圆切点2
PointF drag2 = new PointF();
drag2.x = mDragCenter.x + radius * cos;
drag2.y = mDragCenter.y - radius * sin;
//拖拽圆切点1
PointF drag1 = new PointF();
drag1.x = mDragCenter.x - radius * cos;
drag1.y = mDragCenter.y + radius * sin;
//控制点1
PointF control1 = new PointF();
control1.x = stick1.x + xdelta / 2;
control1.y = stick1.y + ydelta / 2;
//控制点2
PointF control2 = new PointF();
control2.x = stick2.x + xdelta / 2;
control2.y = stick2.y + ydelta / 2;
//贝塞尔曲线
Path path = new Path();
path.moveTo(stick1.x, stick1.y);
path.quadTo(control1.x, control1.y, drag1.x, drag1.y);
path.lineTo(drag2.x, drag2.y);
path.quadTo(control2.x, control2.y, stick2.x, stick2.y);
path.close();
canvas.drawPath(path, mPaint);
}
}
private float downX;
private float downY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
mDragCenter.x += x - downX;
mDragCenter.y += y - downY;
downX = x;
downY = y;
invalidate();
break;
case MotionEvent.ACTION_UP:
final float xoffset = mDragCenter.x - mWidth / 2;
final float yoffset = mDragCenter.y - mHeight / 2;
final float originalx = mDragCenter.x;
final float originaly = mDragCenter.y;
ValueAnimator va = ValueAnimator.ofFloat(0, 1);
va.setInterpolator(new AccelerateDecelerateInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
mDragCenter.x = originalx - xoffset * fraction;
mDragCenter.y = originaly - yoffset * fraction;
invalidate();
}
});
va.setDuration(300);
va.start();
break;
}
return true;
}
}
QQ中的弹性球动画效果
最新推荐文章于 2024-04-02 22:22:27 发布