来不及了,快上车。。。。
不叨叨,上代码
/**
* 类描述:
* 作者:JiaoPeiRong on 2017/3/27 10:12
*/
public class MyBezier extends View {
private Paint mPaint;
private Path mPath;
private float preX;
private float preY;
public MyBezier(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(3);
mPaint.setColor(Color.RED);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath , mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX() , event.getY());
preX = event.getX();
preY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
float endX = (preX + event.getX()) / 2;
float endY = (preY + event.getY()) / 2;
mPath.quadTo(preX ,preY, endX , endY);
preX = event.getX();
preY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onTouchEvent(event);
}
}
基础的贝塞尔曲线我就不讲了,网上一搜一大堆。
单纯的使用path也完全可以实现手势轨迹的捕捉,但是path不如贝塞尔曲线优雅,会有锯齿。代码很简单,我就不啰嗦了。
看这个:
波浪,没错,就是浪!
上代码:
/**
* 类描述:
* 作者:JiaoPeiRong on 2017/3/27 10:56
*/
public class MyBezier2 extends View {
//波长
private float line = 300;
//开始绘制的Y轴坐标
private float myY = 200;
//每次改变的大小
private float dx;
private Paint mPaint;
private Path mPath;
public MyBezier2(Context context, 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_AND_STROKE);
mPaint.setStrokeWidth(3);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
float halfLine = line / 2;
mPath.moveTo(-line + dx , myY);
for (float i = -halfLine ; i < getWidth() + halfLine ; i+=halfLine){
mPath.rQuadTo(halfLine / 2 , 50 , halfLine , 0);
mPath.rQuadTo(halfLine / 2 , -50 , halfLine , 0);
}
mPath.lineTo(getWidth() , getHeight());
mPath.lineTo(0 , getHeight());
mPath.close();
canvas.drawPath(mPath , mPaint);
}
public void startAnim(){
ValueAnimator animator = ValueAnimator.ofFloat(0,line);
animator.setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
dx = (float) animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
}
代码也灰常简单,无非就是画个曲线,然后动画让它动起来,哈哈~
看这个:
仿QQ的效果,代码也很简单哦
/**
* 类描述:
* 作者:JiaoPeiRong on 2017/3/27 11:30
*/
public class MyBezier3 extends FrameLayout {
private float radius = 15;
private float DEFAULT_RADIUS = 15;
private float count = 200;
//原位置的坐标
private float startPointX = count;
private float startPointY = count;
//现位置的坐标
private float curPointX = count;
private float curPointY = count;
private Paint p;
private Path mPath;
//是否在滑动
private boolean isMove = false;
//是否开始帧动画
private boolean isAnimStart = false;
private TextView tv;
private ImageView iv;
public MyBezier3(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.RED);
p.setStyle(Paint.Style.FILL);
mPath = new Path();
//TextView
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tv = new TextView(getContext());
tv.setLayoutParams(layoutParams);
tv.setPadding(5, 5, 5, 5);
tv.setText("99+");
tv.setTextSize(10);
tv.setBackgroundResource(R.drawable.shape_tv_bg);
tv.setTextColor(Color.WHITE);
//ImageView
iv = new ImageView(getContext());
iv.setLayoutParams(layoutParams);
iv.setImageResource(R.drawable.shape_iv_bg);
iv.setVisibility(INVISIBLE);
addView(tv);
addView(iv);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (isAnimStart) {
tv.setX(count);
tv.setY(count);
} else {
canvas.drawCircle(startPointX, startPointY, radius, p);
calculatePath();
canvas.drawPath(mPath, p);
tv.setX(curPointX - tv.getWidth() / 2);
tv.setY(curPointY - tv.getHeight() / 2);
}
super.dispatchDraw(canvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (Math.abs(event.getX() - count) < radius && Math.abs(event.getY() - count) < radius) {
isMove = true;
} else {
isMove = false;
}
return true;
case MotionEvent.ACTION_MOVE:
if (isMove) {
curPointX = event.getX();
curPointY = event.getY();
}
break;
case MotionEvent.ACTION_UP:
curPointX = count;
curPointY = count;
break;
}
invalidate();
return super.onTouchEvent(event);
}
/**
* 计算路径
*/
private void calculatePath() {
float x = curPointX;
float y = curPointY;
float startX = startPointX;
float startY = startPointY;
// 根据角度算出四边形的四个点
float dx = x - startX;
float dy = y - startY;
double a = Math.atan(dy / dx);
float offsetX = (float) (radius * Math.sin(a));
float offsetY = (float) (radius * Math.cos(a));
float distance = (float) Math.sqrt(Math.pow(y - startY, 2) + Math.pow(x - startX, 2));
radius = DEFAULT_RADIUS - distance / 15;
if (radius < 9) {
radius = 9;
isAnimStart = true;
iv.setX(curPointX - iv.getWidth() / 2);
iv.setY(curPointY - iv.getHeight() / 2);
iv.setVisibility(VISIBLE);
((AnimationDrawable) iv.getDrawable()).start();
tv.setVisibility(GONE);
}
// 根据角度算出四边形的四个点
float x1 = startX + offsetX;
float y1 = startY - offsetY;
float x2 = x + offsetX;
float y2 = y - offsetY;
float x3 = x - offsetX;
float y3 = y + offsetY;
float x4 = startX - offsetX;
float y4 = startY + offsetY;
float anchorX = (startX + x) / 2;
float anchorY = (startY + y) / 2;
mPath.reset();
mPath.moveTo(x1, y1);
mPath.quadTo(anchorX, anchorY, x2, y2);
mPath.lineTo(x3, y3);
mPath.quadTo(anchorX, anchorY, x4, y4);
mPath.lineTo(x1, y1);
}
}