本文主要讲的是path对应的常用方法,以及在路径上写文字的drawTextOnPath。还有对绘制圆弧的讲解
效果图:
代码(需要讲解的地方都在注释里)
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
/**
* 路径demo
*/
public class PathView extends View {
private Path mPath_1;// 路径对象(普通直线)
private Path mPath_2;// 路径对象(二阶贝塞尔曲线)
private Path mPath_3;// 路径对象(三阶贝塞尔曲线)
private Path mPath_4;// 路径对象(圆弧)(boolean属性为true)
private Path mPath_5;// 路径对象(圆弧)(boolean属性为false)
private Path mPath_6;// 路径对象(rXXXTo)
private Paint mPaint_1;// 画笔对象(普通直线)
private Paint mPaint_2;// 画笔对象(二阶贝塞尔曲线)
private Paint mPaint_3;// 画笔对象(三阶贝塞尔曲线)
private Paint mPaint_4;// 画笔对象(圆弧)(boolean属性为true)
private Paint mPaint_5;// 画笔对象(圆弧)(boolean属性为false)
private Paint mPaint_6;// 画笔对象(rXXXTo)
//画矩形的画笔
private Paint rectPaint;
//画文字的画笔
private TextPaint mTextPaint;
//二阶贝塞尔曲线的控制点
private Path controlPoint_2;
//三阶贝塞尔曲线的第一个控制点
private Path controlPoint_3_1;
//三阶贝塞尔曲线的第二个控制点
private Path controlPoint_3_2;
//圆弧文字说明路径1
private Path carTextPath_1;
//圆弧文字说明路径2
private Path carTextPath_2;
private Paint pointPaint;//原点画笔
public PathView(Context context, AttributeSet attrs) {
super(context, attrs);
controlPoint_2 = new Path();
controlPoint_3_1 = new Path();
controlPoint_3_2 = new Path();
pointPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
pointPaint.setStyle(Paint.Style.FILL);
pointPaint.setStrokeWidth(20);
pointPaint.setColor(Color.RED);
/**
* 笔触:用笔在画布上点一个点的时候,点出来的样子
* 圆形笔触:ROUND
* 方形笔触:SQUARE
* 方形笔触:BUTT(不会在路径上延伸)(我也不懂,有个资料上是这样写的。但是设置成这个属性,效果和SQUARE一样,我就不解释了,因为不懂)
*/
pointPaint.setStrokeCap(Paint.Cap.ROUND);
//初始化文字画笔。直接打开抗锯齿、防抖动属性。最后的属性不重要,可有可无
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.LINEAR_TEXT_FLAG);
mTextPaint.setColor(Color.DKGRAY);
mTextPaint.setTextSize(25);
mTextPaint.setTextAlign(Paint.Align.CENTER);
/*
* 实例化画笔并设置属性。初始化画笔的时候,打开抗锯齿和防抖动
*/
mPaint_1 = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint_1.setStyle(Paint.Style.STROKE);
mPaint_1.setStrokeWidth(3);
mPaint_1.setColor(Color.CYAN);
// 实例化路径
mPath_1 = new Path();
// 将默认的落笔处(0,0),移动点至[300,300]
mPath_1.moveTo(100, 100);
// 连接路径到点
mPath_1.lineTo(300, 100);
mPath_1.lineTo(400, 200);
mPath_1.lineTo(200, 200);
// 闭合曲线。
//close,只会闭合最近的一个moveTo及它下面的lineTo组成的区域。如果注释掉本行。那么,闭合的区域,就是(31.,250)-(50,300)-(600,120)组成的三角形区域了。
mPath_1.close();
mPath_1.moveTo(310, 250);
mPath_1.lineTo(50, 300);
mPath_1.lineTo(600, 120);
mPath_1.close();
//---------------------------------------------------
mPath_2 = new Path();
//把画笔mPaint_1的属性给mPaint_2。或者说,按照mPaint_1的样子创建一个mPaint_2。
mPaint_2 = new Paint(mPaint_1);
mPaint_2.setColor(Color.RED);
mPath_2.moveTo(400, 600);//起点
//mPath_2.lineTo(600, 120);
/**
* 前2个参数:二阶贝塞尔曲线的控制点坐标
* 后2个参数:终点坐标
*/
//起点是quadTo方法上面的最近的一个点
mPath_2.quadTo(500, 700, 600, 600);
controlPoint_2.moveTo(400, 710);
controlPoint_2.lineTo(600, 710);
//---------------------------------------------------
//三阶贝塞尔曲线。前2个参数是第一个控制点坐标;中间2个参数是第二个控制点坐标;最后2个参数是终点坐标
//cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
mPath_3 = new Path();
mPaint_3 = new Paint(mPaint_1);
mPaint_3.setColor(Color.BLUE);
mPath_3.moveTo(300, 900);//起点
mPath_3.cubicTo(400, 800, 500, 1000, 600, 900);
controlPoint_3_1.moveTo(300, 790);
controlPoint_3_1.lineTo(500, 790);
controlPoint_3_2.moveTo(400, 1010);
controlPoint_3_2.lineTo(600, 1010);
//---------------------------------------------------
carTextPath_1 = new Path();
mPath_4 = new Path();
mPaint_4 = new Paint(mPaint_1);
mPaint_4.setColor(Color.parseColor("#ec434b"));
mPath_4.moveTo(500, 1100);
RectF rf_1 = new RectF(500, 1100, 800, 1400);
//值为true时将会把弧的起点作为Path的起点。如果不有这个有boolean值的方法,默认是false
mPath_4.arcTo(rf_1, 0, 90, true);
carTextPath_1.moveTo(500, 1100);
carTextPath_1.lineTo(800, 1100);
rectPaint = new Paint(mPaint_1);
//---------------------------------------------------
carTextPath_2 = new Path();
mPath_5 = new Path();
mPaint_5 = new Paint(mPaint_1);
mPaint_5.setColor(Color.parseColor("#ec434b"));
mPath_5.moveTo(700, 400);
RectF rf_2 = new RectF(700, 400, 1000, 700);
//写false和不用这个参数,效果一样
//mPath_5.arcTo(rf_2, 0, 90);
mPath_5.arcTo(rf_2, 0, 90, false);
carTextPath_2.moveTo(700, 400);
carTextPath_2.lineTo(1000, 400);
rectPaint = new Paint(mPaint_1);
//---------------------------------------------------
mPaint_6 = new Paint(mPaint_1);
mPaint_6.setColor(Color.BLACK);
mPath_6 = new Path();
mPath_6.moveTo(200, 1100);
//rXXXTo:以上一个点,作为原点。而不是以(0,0)作为原点
mPath_6.rLineTo(300, 600);
}
@Override
protected void onDraw(Canvas canvas) {
// 绘制路径
canvas.drawPath(mPath_1, mPaint_1);
canvas.drawPath(mPath_2, mPaint_2);
canvas.drawPath(mPath_3, mPaint_3);
canvas.drawPath(mPath_4, mPaint_4);
canvas.drawPath(mPath_5, mPaint_5);
canvas.drawPath(mPath_6, mPaint_6);
//辅助矩形。用于理解圆弧的绘制
canvas.drawRect(new RectF(700, 400, 1000, 700), rectPaint);
canvas.drawRect(new RectF(500, 1100, 800, 1400), rectPaint);
canvas.drawPoint(500, 700, pointPaint);
/**
* 第2个参数,表示绘制文字的路径。即:在哪个路径上绘制文字。要注意:这个路径一定要有长度,不要在一个“点”上绘制文字,否则,看不到文字
* 第3(X轴)和第4参数(Y轴),表示文字位置的偏移值
*/
canvas.drawTextOnPath("二阶控制点", controlPoint_2, 0, 25, mTextPaint);
canvas.drawPoint(400, 800, pointPaint);
canvas.drawTextOnPath("三阶第一个控制点", controlPoint_3_1, 0, -5, mTextPaint);
canvas.drawPoint(500, 1000, pointPaint);
canvas.drawTextOnPath("三阶第二个控制点", controlPoint_3_2, 0, 25, mTextPaint);
canvas.drawTextOnPath("二阶贝塞尔曲线", mPath_2, 0, -5, mTextPaint);
canvas.drawTextOnPath("三阶贝塞尔曲线", mPath_3, 0, -5, mTextPaint);
canvas.drawTextOnPath("把弧的起点作为Path的起点", carTextPath_1, 0, -5, mTextPaint);
canvas.drawTextOnPath("不把弧的起点作为Path的起点", carTextPath_2, 0, -5, mTextPaint);
}
}
接下来,只需要在布局文件中用一下就行
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.chen.customviewdemo.view.PathView
android:id="@+id/bitmapMeshView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
在Activity中,不用做任何操作,主要就是了解这个自定义view中的那些API
/**
* 路径demo
*/
public class MainActivity_16_PathView extends BaseActivity {
@Override
void initview() {
setContentView(R.layout.activity_main_16);
}
}