从细节上更进一步的授课自定义View的事无巨细绘制方法,倘诺把自定义View比作盖壹座房子

上篇小说介绍了自定义View的创建流程,从微观上提交了三个自定义View的始建步骤,本篇是上一篇文章的接轨,介绍了自定义View中三个必备的工具Canvas和Paint,从细节上更进一步的教学自定义View的详尽绘制方法。要是把自定义View比作盖一座房屋,那么上篇文章就一定于教会了我们怎么一步步的搭建房子的骨子,而本篇作品就要教会我们的是为房子的龙骨添砖加瓦直至成型,甚至是怎么装修。

上篇小说介绍了自定义View的创始流程,从宏观上提交了四个自定义View的创制步骤,本篇是上壹篇文章的承继,介绍了自定义View中三个必备的工具Canvas和Paint,从细节上更进一步的上书自定义View的详实绘制方法。就算把自定义View比作盖一座房子,那么上篇文章就也正是教会了大家怎么一步步的搭建房子的龙骨,而本篇小说就要教会大家的是为房屋的骨子添砖加瓦直至成型,甚至是怎么装修。

Canvas

为了后文更为便利的任课Canvas的常用方法的行使,大家先来做一些准备干活,创设二个自定义View框架,先发轫化一下Paint画笔,并设置相关措施:

public class StudyView extends View {

    private Paint mPaint;
    private Context mContext;

    public StudyView(Context context) {
        super(context);
        init(context);
    }

    public StudyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStrokeWidth(5); // 设置笔尖宽度
        mPaint.setStyle(Paint.Style.STROKE); // 不填充
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

Canvas

为了后文更为有利于的任课Canvas的常用方法的使用,我们先来做壹些预备干活,创设二个自定义View框架,先起初化一下Paint画笔,并设置相关方法:

public class StudyView extends View {

    private Paint mPaint;
    private Context mContext;

    public StudyView(Context context) {
        super(context);
        init(context);
    }

    public StudyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStrokeWidth(5); // 设置笔尖宽度
        mPaint.setStyle(Paint.Style.STROKE); // 不填充
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

制图圆弧和扇形

Canvas提供drawArc()方法,通过传递不相同的参数可用来绘制圆弧和扇形,此方法有七个重载方法,详细参数如下:

  • drawArc(float left, float top, float right, float bottom, float
    startAngle, float sweepAngle, boolean useCenter, Paint paint)
  1. left:扇形或圆弧所占区域的左边界线x坐标
  2. top:扇形或圆弧所占区域的上方界线y坐标
  3. right:左边界线x坐标
  4. bottom:上面界线y坐标
  5. startAngle:扇形或圆弧的前奏角度
  6. sweepAngle:扫过的角度
  7. userCenter:此参数能够驾驭为true正是画扇形,false正是画圆弧
  8. paint:画笔
  • drawArc(RectF oval, float startAngle, float sweepAngle, boolean
    useCenter, Paint paint)

此格局第多少个参数是七个RectF类,也是境界,正是把多少个办法的left,top,right,bottom封装到了RectF类中,剩余参数与上1个主意同样。

接下去用着多少个重载方法分别绘制五个90°的扇形和五个90°的半圆形:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 绘制扇形
    canvas.drawArc(0, 0, 200, 200, 0, 90, true, mPaint);
    RectF rectF = new RectF(0, 0, 200, 200);
    canvas.drawArc(rectF, 180, 90, true, mPaint);

    // 绘制圆弧
    canvas.drawArc(300, 0, 500, 200, 0, 90, false, mPaint);
    RectF rectF1 = new RectF(300, 0, 500, 200);
    canvas.drawArc(rectF1, 180, 90, false, mPaint);
}

制图效果如下图所示,此外索要证实的一些是,drawArc的第四个参数startAngle中的角度,0°是指坐标系中第4象限中与x重合的角度,顺时针方向代表角度增大的样子,如下图中革命线条所示。

图片 1

绘图圆弧和扇形

Canvas提供drawArc()方法,通过传递区别的参数可用来绘制圆弧和扇形,此方法有七个重载方法,详细参数如下:

  • drawArc(float left, float top, float right, float bottom, float
    startAngle, float sweepAngle, boolean useCenter, Paint paint)
  1. left:扇形或圆弧所占区域的左边界线x坐标
  2. top:扇形或圆弧所占区域的上边界线y坐标
  3. right:右侧界线x坐标
  4. bottom:下面界线y坐标
  5. startAngle:扇形或圆弧的初始角度
  6. sweepAngle:扫过的角度
  7. userCenter:此参数能够驾驭为true正是画扇形,false正是画圆弧
  8. paint:画笔
  • drawArc(RectF oval, float startAngle, float sweepAngle, boolean
    useCenter, Paint paint)

此方法第三个参数是三个RectF类,也是境界,就是把3个形式的left,top,right,bottom封装到了RectF类中,剩余参数与上1个办法一致。

接下去用着多少个重载方法分别绘制八个90°的扇形和多少个90°的弧形:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 绘制扇形
    canvas.drawArc(0, 0, 200, 200, 0, 90, true, mPaint);
    RectF rectF = new RectF(0, 0, 200, 200);
    canvas.drawArc(rectF, 180, 90, true, mPaint);

    // 绘制圆弧
    canvas.drawArc(300, 0, 500, 200, 0, 90, false, mPaint);
    RectF rectF1 = new RectF(300, 0, 500, 200);
    canvas.drawArc(rectF1, 180, 90, false, mPaint);
}

绘制效果如下图所示,其它部要求要验证的1些是,drawArc的第伍个参数startAngle中的角度,0°是指坐标系中第六象限中与x重合的角度,顺时针方向代表角度增大的趋势,如下图中革命线条所示。

图片 2

绘制Bitmap

在Canvas中提供了drawBitmap方法,此办法能够让大家直接拿走一张图纸绘制到画布上,有了它能够让大家的自定义View如虎生翼,同时也让我们兑现部分错综复杂效果有了一个更为有利于的门路。上边是drawBitmap的几个相比较常用的重载方法:

  • drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
  1. bitmap:Bitmap财富文件
  2. left和top:代表了图片左上角落入的职分坐标。
  3. top:看2
  4. paint:画笔
  • drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
  1. src:在Bitmap图片上截取1部分作为绘制源,可null
  2. det:将绘制目标拉伸平铺到det内定的矩形中
  • drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
    同第二个重载方法,大致一毛同样。

  • drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

  1. matrix:Matrix的参数字传送入是的drawBitmap作用变得卓殊强硬,让此格局有意思了众多,通过matrix能够完毕图片的移位(postTranslate())、缩放(postScale())、旋转(postRotate())、错切(postSkew())等等花式炫人眼目效果,由于Matrix的用法稍微多1些,篇幅限制,那里就先1带而过了,感兴趣的朋友能够自行研究。

在onDraw方法中drawBitmap的如上重载方法,注目的在于选用完Bitmap之后记得用Bitmap.recycle()来回收掉能源,以幸免oom。

/** drawBitmap */
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), android.R.mipmap.sym_def_app_icon);
// 绘制图片
canvas.drawBitmap(bitmap, 0, 300, null);
// 将图片拉伸平铺在RectF矩形内
canvas.drawBitmap(bitmap, null, new RectF(200, 300, 500, 500), null);
// 截取图片的四分之一拉伸平铺在RectF矩形内
canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2), new RectF(500, 300, 800, 500), null);

Matrix matrix = new Matrix();
matrix.postTranslate(800, 300); // 将bitmap平移到此位置
canvas.drawBitmap(bitmap, matrix, mPaint);

// 为防止oom,及时回收bitmap
bitmap.recycle();

功效如下图(红框内)。

图片 3

绘制Bitmap

在Canvas中提供了drawBitmap方法,此办法能够让我们直接获取一张图片绘制到画布上,有了它可以让大家的自定义View为虎添翼,同时也让咱们兑现部分错综复杂效果有了3个更为有利于的路子。下边是drawBitmap的多少个相比较常用的重载方法:

  • drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
  1. bitmap:Bitmap财富文件
  2. left和top:代表了图片左上角落入的职分坐标。
  3. top:看2
  4. paint:画笔
  • drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
  1. src:在Bitmap图片上截取一有些作为绘制源,可null
  2. det:将绘制目的拉伸平铺到det钦命的矩形中
  • drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
    同第四个重载方法,大概第一毛纺织厂同样。

  • drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

  1. matrix:Matrix的参数字传送入是的drawBitmap作用变得老大强硬,让此方法有趣了成都百货上千,通过matrix能够兑现图片的移位(postTranslate())、缩放(postScale())、旋转(postRotate())、错切(postSkew())等等花式炫彩效果,由于Matrix的用法稍微多一些,篇幅限制,那里就先1带而过了,感兴趣的朋友能够自动查究。

在onDraw方法中drawBitmap的上述重载方法,注目的在于应用完Bitmap之后记得用Bitmap.recycle()来回收掉能源,以免备oom。

/** drawBitmap */
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), android.R.mipmap.sym_def_app_icon);
// 绘制图片
canvas.drawBitmap(bitmap, 0, 300, null);
// 将图片拉伸平铺在RectF矩形内
canvas.drawBitmap(bitmap, null, new RectF(200, 300, 500, 500), null);
// 截取图片的四分之一拉伸平铺在RectF矩形内
canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2), new RectF(500, 300, 800, 500), null);

Matrix matrix = new Matrix();
matrix.postTranslate(800, 300); // 将bitmap平移到此位置
canvas.drawBitmap(bitmap, matrix, mPaint);

// 为防止oom,及时回收bitmap
bitmap.recycle();

效果如下图(红框内)。

图片 4

绘图圆形

  • drawCircle(float cx, float cy, float radius, Paint paint)
  1. cx:圆心x坐标
  2. cy:圆心y坐标
  3. radius:半径

canvas.drawCircle(100, 700, 100, mPaint);

功效如下图:

图片 5

绘制圆形

  • drawCircle(float cx, float cy, float radius, Paint paint)
  1. cx:圆心x坐标
  2. cy:圆心y坐标
  3. radius:半径

canvas.drawCircle(100, 700, 100, mPaint);

职能如下图:

图片 6

绘制点

  • drawPoint(float x, float y, Paint paint)
  1. x:点的x坐标
  2. y:点的y坐标
  • drawPoints(float[] pts, Paint paint) 绘制一组点
  1. pts:float数组,两位为1组,两两整合代表x、y坐标,例如:pts[0]、pts[1]代表首先个点的x、y坐标,pts[2]、pts[3]意味着第2个点的x、y坐标,依次类推。
  • drawPoints(float[] pts, int offset, int count, Paint paint)
    绘制1组点
  1. pts:float数组,两位为壹组,两两整合代表x、y坐标,例如:pts[0]、pts[1]表示第贰个点的x、y坐标,pts[2]、pts[3]表示第三个点的x、y坐标,依次类推。
  2. offset:代表数组开首跳过多少个只开头绘制点,注意那里不是指数组的下标,而是表示跳过多少个值。
  3. count:在跳过offset个值后,处理多少个值,注意那里的count不是代表点的个数,而是表示数组中值的个数。

canvas.drawPoint(100, 700, mPaint); // 绘制一个点

float[] points = new float[] {
    130, 700,
    160, 700,
    190, 700,
    210, 700,
    240, 700
};

canvas.drawPoints(points, 2, 4, mPaint); // 绘制一组点(代表跳过前两个值,处理4个值,也就是实际绘制2个点)

功用如下图:

图片 7

绘制点

  • drawPoint(float x, float y, Paint paint)
  1. x:点的x坐标
  2. y:点的y坐标
  • drawPoints(float[] pts, Paint paint) 绘制一组点
  1. pts:float数组,两位为一组,两两结缘代表x、y坐标,例如:pts[0]、pts[1]表示首先个点的x、y坐标,pts[2]、pts[3]表示第三个点的x、y坐标,依次类推。
  • drawPoints(float[] pts, int offset, int count, Paint paint)
    绘制1组点
  1. pts:float数组,两位为一组,两两整合代表x、y坐标,例如:pts[0]、pts[1]表示第叁个点的x、y坐标,pts[2]、pts[3]表示第3个点的x、y坐标,依次类推。
  2. offset:代表数组先河跳过多少个只起初绘制点,注意那里不是指数组的下标,而是表示跳过多少个值。
  3. count:在跳过offset个值后,处理几个值,注意那里的count不是代表点的个数,而是意味着数组中值的个数。

canvas.drawPoint(100, 700, mPaint); // 绘制一个点

float[] points = new float[] {
    130, 700,
    160, 700,
    190, 700,
    210, 700,
    240, 700
};

canvas.drawPoints(points, 2, 4, mPaint); // 绘制一组点(代表跳过前两个值,处理4个值,也就是实际绘制2个点)

作用如下图:

图片 8

绘制椭圆

  • drawOval(float left, float top, float right, float bottom, Paint
    paint)
  1. left
  2. top
  3. right
  4. bottom

在left、top、right、bottom围成的区域内绘制1个椭圆。

  • drawOval(RectF oval, Paint paint)
  1. 将第3个重载方法的left、top、right、bottom封装到RectF类中,与扇形的重载方法异曲同工。

RectF rectF2 = new RectF(300, 600, 700, 800); // 创建一个RectF
canvas.drawOval(rectF2, mPaint);

成效如下图:

图片 9

制图椭圆

  • drawOval(float left, float top, float right, float bottom, Paint
    paint)
  1. left
  2. top
  3. right
  4. bottom

在left、top、right、bottom围成的区域内绘制1个椭圆。

  • drawOval(RectF oval, Paint paint)
  1. 将首先个重载方法的left、top、right、bottom封装到RectF类中,与扇形的重载方法异曲同工。

RectF rectF2 = new RectF(300, 600, 700, 800); // 创建一个RectF
canvas.drawOval(rectF2, mPaint);

职能如下图:

图片 10

绘制矩形

  • drawRect(float left, float top, float right, float bottom, Paint
    paint)
  • drawRect(Rect r, Paint paint)
  • drawRect(RectF rect, Paint paint)

drawRect的参数非凡好精晓,这里就不啰嗦了,间接上代码看作用:

canvas.drawRect(rectF2, mPaint);

注:这里的rectF2即上文绘制椭圆时创造的RectF对象。

图片 11

绘图矩形

  • drawRect(float left, float top, float right, float bottom, Paint
    paint)
  • drawRect(Rect r, Paint paint)
  • drawRect(RectF rect, Paint paint)

drawRect的参数卓殊好驾驭,那里就不啰嗦了,直接上代码看作用:

canvas.drawRect(rectF2, mPaint);

注:那里的rectF二即上文绘制椭圆时创设的RectF对象。

图片 12

制图圆角矩形

  • drawRoundRect(float left, float top, float right, float bottom,
    float rx, float ry, Paint paint)
  • drawRoundRect(RectF rect, float rx, float ry, Paint paint)

drawRoundRect是绘制圆角矩形,用法和drawRect类似,唯一分裂的是多了五个参数:

  1. rx:x轴方向的圆角弧度
  2. ry:y轴方向的圆角弧度

上代码,看效果:

canvas.drawRoundRect(rectF2, 60, 30, mPaint);

那边为了突出七个趋势的圆角弧度,特地将rx和ry设置差别一点都非常大,效果如下图:

图片 13

绘制圆角矩形

  • drawRoundRect(float left, float top, float right, float bottom,
    float rx, float ry, Paint paint)
  • drawRoundRect(RectF rect, float rx, float ry, Paint paint)

drawRoundRect是绘制圆角矩形,用法和drawRect类似,唯一差异的是多了四个参数:

  1. rx:x轴方向的圆角弧度
  2. ry:y轴方向的圆角弧度

上代码,看效果:

canvas.drawRoundRect(rectF2, 60, 30, mPaint);

那里为了卓越七个趋势的圆角弧度,特地将rx和ry设置差异一点都不小,效果如下图:

图片 14

绘图直线

  • drawLine(float startX, float startY, float stopX, float stopY, Paint
    paint)
  • drawLines(float[] pts, int offset, int count, Paint paint)
  • drawLines(float[] pts, Paint paint)

drawLine和drawLines2个是绘制三个点,1个是绘制1组点,当中drawLines中的float数组中四个值为1组点,其用法能够参照drawPoints。

canvas.drawLine(100, 820, 800, 820, mPaint);

float[] lines = new float[]{
        100f, 850f, 800f, 850f,
        100f, 900f, 800f, 900f,
        100f, 950f, 800f, 950f
};
canvas.drawLines(lines, mPaint); // 按floats数组中,四个数为1组,绘制多条线

效益如下图:

图片 15

制图直线

  • drawLine(float startX, float startY, float stopX, float stopY, Paint
    paint)
  • drawLines(float[] pts, int offset, int count, Paint paint)
  • drawLines(float[] pts, Paint paint)

drawLine和drawLines1个是绘制三个点,3个是绘制壹组点,当中drawLines中的float数组中八个值为1组点,其用法能够参考drawPoints。

canvas.drawLine(100, 820, 800, 820, mPaint);

float[] lines = new float[]{
        100f, 850f, 800f, 850f,
        100f, 900f, 800f, 900f,
        100f, 950f, 800f, 950f
};
canvas.drawLines(lines, mPaint); // 按floats数组中,四个数为1组,绘制多条线

效益如下图:

图片 16

drawPath() 绘制不规则图形

上边的那么些Canvas方法纵然已经很有力了,可是大家只要想要绘制壹些十分的图片怎么办,那时候就要用到有力的drawPath()方法了,通过对Path实行安装分歧的坐标、增加区别图形,最终传入drawPath方法中能够绘制出复杂的且不规则的形状。以下是draw帕特h的措施及参数:

  • drawPath(Path path, Paint paint)

此处的首要性参数正是Path,Path类的点子较多,大多数用法类似,那里挑几个说一下:

  • Path类
  1. addArc(RectF oval, float startAngle, float sweepAngle)
    往path里面加多二个弧形
  2. addCircle(float x, float y, float radius, Path.Direction dir)
    增加三个圆形
  3. addOval(RectF oval, Path.Direction dir) 增多1个椭圆
  4. addRect(RectF rect, Path.Direction dir) 增多3个矩形
  5. lineTo(float x, float y) 连线到坐标(x,y)
  6. moveTo(float x, float y) 将path绘制点运动到坐标(x,y)
  7. close()
    用直线闭合图形,调用此办法后,path会将最后一处点与初始用直线连接起来,path伊始点为moveTo()方法的坐标上,若是未有调用moveTo()初始点将默以为(0,0)坐标。

接下去使用drawPath绘制贰个阶梯:

// 使用 Path 绘制一个楼梯
Path path = new Path();
path.lineTo(0, 1000);
path.lineTo(100, 1000);
path.lineTo(100, 1100);
path.lineTo(200, 1100);
path.lineTo(200, 1200);
path.lineTo(300, 1200);
path.lineTo(300, 1300);
path.lineTo(400, 1300);
path.lineTo(400, 1400);
path.lineTo(0, 1400);
path.lineTo(0, 1000);
path.close();
canvas.drawPath(path, mPaint);

效果如下图:

图片 17

再用drawPath方法绘制二个Android小机器人:

/ 使用 Path 绘制一个Android机器人
// 绘制两个触角
path.reset();
path.moveTo(625, 1050);
path.lineTo(650, 1120);
path.moveTo(775, 1050);
path.lineTo(750, 1120);

path.addArc(new RectF(600, 1100, 800, 1300), 180, 180); // 绘制头部
path.addCircle(666.66f, 1150, 10, Path.Direction.CW); // 绘制眼睛,CW:顺时针绘制, CCW:逆时针绘制
path.addCircle(733.33f, 1150, 10, Path.Direction.CW);
path.addRect(new RectF(600, 1200, 800, 1300), Path.Direction.CW);  // 身体
canvas.drawPath(path, mPaint);

功能图如下:

图片 18

末尾,上文中Canvas示例的万事代码如下:

public class StudyView extends View {

    private Paint mPaint;
    private Context mContext;

    public StudyView(Context context) {
        super(context);
        init(context);
    }

    public StudyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStrokeWidth(5); // 设置笔尖宽度
        mPaint.setStyle(Paint.Style.STROKE); // 不填充
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /** 1、drawArc */

        // 绘制扇形
        canvas.drawArc(0, 0, 200, 200, 0, 90, true, mPaint);
        RectF rectF = new RectF(0, 0, 200, 200);
        canvas.drawArc(rectF, 180, 90, true, mPaint);

        // 绘制圆弧
        canvas.drawArc(300, 0, 500, 200, 0, 90, false, mPaint);
        RectF rectF1 = new RectF(300, 0, 500, 200);
        canvas.drawArc(rectF1, 180, 90, false, mPaint);

        /** 2、drawBitmap */
        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), android.R.mipmap.sym_def_app_icon);
        // 绘制图片
        canvas.drawBitmap(bitmap, 0, 300, null);
        // 将图片拉伸平铺在RectF矩形内
        canvas.drawBitmap(bitmap, null, new RectF(200, 300, 500, 500), null);
        // 截取图片的四分之一拉伸平铺在RectF矩形内
        canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2), new RectF(500, 300, 800, 500), null);

        Matrix matrix = new Matrix();
        matrix.postTranslate(800, 300); // 将bitmap平移到此位置
        canvas.drawBitmap(bitmap, matrix, mPaint);

        // 为防止oom,及时回收bitmap
        bitmap.recycle();

        /** 3、drawCircle */
        canvas.drawCircle(100, 700, 100, mPaint);

        /** 4、绘制一个点 */
        canvas.drawPoint(100, 700, mPaint); // 绘制一个点

        float[] points = new float[] {
            130, 700,
            160, 700,
            190, 700,
            210, 700,
            240, 700
        };

        canvas.drawPoints(points, 2, 4, mPaint); // 绘制一组点(代表跳过前两个值,处理4个值,也就是实际绘制2个点)


        RectF rectF2 = new RectF(300, 600, 700, 800); // 创建一个RectF

        /** 5、drawOval 绘制椭圆 */
        canvas.drawOval(rectF2, mPaint);

        /** 6、drawRect 绘制矩形*/
        canvas.drawRect(rectF2, mPaint);
        canvas.drawRoundRect(rectF2, 60, 30, mPaint);

        /** 7、drawLine */
        canvas.drawLine(100, 820, 800, 820, mPaint);

        float[] lines = new float[]{
                100f, 850f, 800f, 850f,
                100f, 900f, 800f, 900f,
                100f, 950f, 800f, 950f
        };
        canvas.drawLines(lines, mPaint); // 按floats数组中,四个数为1组,绘制多条线


        /** 8、drawPath */

        // 使用 Path 绘制一个楼梯
        Path path = new Path();
        path.moveTo(0, 1000);
        path.lineTo(100, 1000);
        path.lineTo(100, 1100);
        path.lineTo(200, 1100);
        path.lineTo(200, 1200);
        path.lineTo(300, 1200);
        path.lineTo(300, 1300);
        path.lineTo(400, 1300);
        path.lineTo(400, 1400);
        path.close();
        canvas.drawPath(path, mPaint);

        // 使用 Path 绘制一个Android机器人

        // 绘制两个触角
        path.reset();
        path.moveTo(625, 1050);
        path.lineTo(650, 1120);
        path.moveTo(775, 1050);
        path.lineTo(750, 1120);

        path.addArc(new RectF(600, 1100, 800, 1300), 180, 180); // 绘制头部
        path.addCircle(666.66f, 1150, 10, Path.Direction.CW); // 绘制眼睛,CW:顺时针绘制, CCW:逆时针绘制
        path.addCircle(733.33f, 1150, 10, Path.Direction.CW);
        path.addRect(new RectF(600, 1200, 800, 1300), Path.Direction.CW);  // 身体
        canvas.drawPath(path, mPaint);
    }
}

完整意义图如下:

图片 19

其实Canvas除了能够绘制图形之外,还足以绘制文字,Canvas的绘图像和文字字的方法有drawText()、drawTextOnPath()、drawTextRun()等方式,在绘制文字是和Paint的整合越发严格,所以讲绘制文字的点子放在下文和Paint一起讲大概功效会更加好有的,好了,废话不多说了,接下去大家就起来Paint的篇章。

drawPath() 绘制不规则图形

地点的那个Canvas方法纵然已经很强劲了,不过大家若是想要绘制一些不规则的图纸咋办,那时候将要用到无敌的draw帕特h()方法了,通过对Path实行设置差异的坐标、增多差别图形,最终传入drawPath方法中能够绘制出复杂的且不规则的形象。以下是drawPath的方法及参数:

  • drawPath(Path path, Paint paint)

此处的要害参数正是Path,Path类的章程较多,大多数用法类似,那里挑几个说一下:

  • Path类
  1. addArc(RectF oval, float startAngle, float sweepAngle)
    往path里面增多三个半圆
  2. addCircle(float x, float y, float radius, Path.Direction dir)
    增多一个圆形
  3. addOval(RectF oval, Path.Direction dir) 增多叁个椭圆
  4. addRect(RectF rect, Path.Direction dir) 增加叁个矩形
  5. lineTo(float x, float y) 连线到坐标(x,y)
  6. moveTo(float x, float y) 将path绘制点运动到坐标(x,y)
  7. close()
    用直线闭合图形,调用此办法后,path会将最终一处点与早先用直线连接起来,path初始点为moveTo()方法的坐标上,尽管未有调用moveTo()起头点将默以为(0,0)坐标。

接下去使用drawPath绘制三个阶梯:

// 使用 Path 绘制一个楼梯
Path path = new Path();
path.lineTo(0, 1000);
path.lineTo(100, 1000);
path.lineTo(100, 1100);
path.lineTo(200, 1100);
path.lineTo(200, 1200);
path.lineTo(300, 1200);
path.lineTo(300, 1300);
path.lineTo(400, 1300);
path.lineTo(400, 1400);
path.lineTo(0, 1400);
path.lineTo(0, 1000);
path.close();
canvas.drawPath(path, mPaint);

功用如下图:

图片 20

再用drawPath方法绘制多个Android小机器人:

/ 使用 Path 绘制一个Android机器人
// 绘制两个触角
path.reset();
path.moveTo(625, 1050);
path.lineTo(650, 1120);
path.moveTo(775, 1050);
path.lineTo(750, 1120);

path.addArc(new RectF(600, 1100, 800, 1300), 180, 180); // 绘制头部
path.addCircle(666.66f, 1150, 10, Path.Direction.CW); // 绘制眼睛,CW:顺时针绘制, CCW:逆时针绘制
path.addCircle(733.33f, 1150, 10, Path.Direction.CW);
path.addRect(new RectF(600, 1200, 800, 1300), Path.Direction.CW);  // 身体
canvas.drawPath(path, mPaint);

职能图如下:

图片 21

终极,上文中Canvas示例的全套代码如下:

public class StudyView extends View {

    private Paint mPaint;
    private Context mContext;

    public StudyView(Context context) {
        super(context);
        init(context);
    }

    public StudyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStrokeWidth(5); // 设置笔尖宽度
        mPaint.setStyle(Paint.Style.STROKE); // 不填充
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /** 1、drawArc */

        // 绘制扇形
        canvas.drawArc(0, 0, 200, 200, 0, 90, true, mPaint);
        RectF rectF = new RectF(0, 0, 200, 200);
        canvas.drawArc(rectF, 180, 90, true, mPaint);

        // 绘制圆弧
        canvas.drawArc(300, 0, 500, 200, 0, 90, false, mPaint);
        RectF rectF1 = new RectF(300, 0, 500, 200);
        canvas.drawArc(rectF1, 180, 90, false, mPaint);

        /** 2、drawBitmap */
        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), android.R.mipmap.sym_def_app_icon);
        // 绘制图片
        canvas.drawBitmap(bitmap, 0, 300, null);
        // 将图片拉伸平铺在RectF矩形内
        canvas.drawBitmap(bitmap, null, new RectF(200, 300, 500, 500), null);
        // 截取图片的四分之一拉伸平铺在RectF矩形内
        canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2), new RectF(500, 300, 800, 500), null);

        Matrix matrix = new Matrix();
        matrix.postTranslate(800, 300); // 将bitmap平移到此位置
        canvas.drawBitmap(bitmap, matrix, mPaint);

        // 为防止oom,及时回收bitmap
        bitmap.recycle();

        /** 3、drawCircle */
        canvas.drawCircle(100, 700, 100, mPaint);

        /** 4、绘制一个点 */
        canvas.drawPoint(100, 700, mPaint); // 绘制一个点

        float[] points = new float[] {
            130, 700,
            160, 700,
            190, 700,
            210, 700,
            240, 700
        };

        canvas.drawPoints(points, 2, 4, mPaint); // 绘制一组点(代表跳过前两个值,处理4个值,也就是实际绘制2个点)


        RectF rectF2 = new RectF(300, 600, 700, 800); // 创建一个RectF

        /** 5、drawOval 绘制椭圆 */
        canvas.drawOval(rectF2, mPaint);

        /** 6、drawRect 绘制矩形*/
        canvas.drawRect(rectF2, mPaint);
        canvas.drawRoundRect(rectF2, 60, 30, mPaint);

        /** 7、drawLine */
        canvas.drawLine(100, 820, 800, 820, mPaint);

        float[] lines = new float[]{
                100f, 850f, 800f, 850f,
                100f, 900f, 800f, 900f,
                100f, 950f, 800f, 950f
        };
        canvas.drawLines(lines, mPaint); // 按floats数组中,四个数为1组,绘制多条线


        /** 8、drawPath */

        // 使用 Path 绘制一个楼梯
        Path path = new Path();
        path.moveTo(0, 1000);
        path.lineTo(100, 1000);
        path.lineTo(100, 1100);
        path.lineTo(200, 1100);
        path.lineTo(200, 1200);
        path.lineTo(300, 1200);
        path.lineTo(300, 1300);
        path.lineTo(400, 1300);
        path.lineTo(400, 1400);
        path.close();
        canvas.drawPath(path, mPaint);

        // 使用 Path 绘制一个Android机器人

        // 绘制两个触角
        path.reset();
        path.moveTo(625, 1050);
        path.lineTo(650, 1120);
        path.moveTo(775, 1050);
        path.lineTo(750, 1120);

        path.addArc(new RectF(600, 1100, 800, 1300), 180, 180); // 绘制头部
        path.addCircle(666.66f, 1150, 10, Path.Direction.CW); // 绘制眼睛,CW:顺时针绘制, CCW:逆时针绘制
        path.addCircle(733.33f, 1150, 10, Path.Direction.CW);
        path.addRect(new RectF(600, 1200, 800, 1300), Path.Direction.CW);  // 身体
        canvas.drawPath(path, mPaint);
    }
}

总体意义图如下:

图片 22

事实上Canvas除了能够绘制图形之外,还能绘制文字,Canvas的绘图像和文字字的法子有drawText()、drawTextOnPath()、drawTextRun()等艺术,在绘制文字是和Paint的组成特别严格,所以讲绘制文字的主意放在下文和Paint一同讲或者作用会更加好有的,好了,废话不多说了,接下去大家就起来Paint的篇章。

Paint

为了尤其清晰的助教Paint的用法,先来新建一个自定义类,暂叫PaintStudyView,接下去创立二个它的大致骨架,在此类中定义了有的变量,变量的意思请见注释:

public class PaintStudyView extends View {

    private Paint mTextPaint;  // 绘制文字的Paint
    private Paint mPointPaint; // 绘制参考点的Paint
    private Context mContext;

    private final static float Y_SPACE = 100; // y轴方向的间距

    public PaintStudyView(Context context) {
        super(context);
        init(context);
    }

    public PaintStudyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true); // 消除锯齿
        mTextPaint.setStrokeWidth(1); // 设置笔尖宽度
        mTextPaint.setStyle(Paint.Style.FILL); // 填充
        mTextPaint.setTextSize(30);

        mPointPaint = new Paint();
        mPointPaint.setAntiAlias(true);
        mPointPaint.setStrokeWidth(5);
        mPointPaint.setColor(Color.RED); // 将参考点的Paint设置为红色
        mPointPaint.setStyle(Paint.Style.STROKE);// 不填充
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

Paint

为了进一步明显的解说Paint的用法,先来新建3个自定义类,暂叫PaintStudyView,接下去创立一个它的大致骨架,在此类中定义了有些变量,变量的意思请见注释:

public class PaintStudyView extends View {

    private Paint mTextPaint;  // 绘制文字的Paint
    private Paint mPointPaint; // 绘制参考点的Paint
    private Context mContext;

    private final static float Y_SPACE = 100; // y轴方向的间距

    public PaintStudyView(Context context) {
        super(context);
        init(context);
    }

    public PaintStudyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true); // 消除锯齿
        mTextPaint.setStrokeWidth(1); // 设置笔尖宽度
        mTextPaint.setStyle(Paint.Style.FILL); // 填充
        mTextPaint.setTextSize(30);

        mPointPaint = new Paint();
        mPointPaint.setAntiAlias(true);
        mPointPaint.setStrokeWidth(5);
        mPointPaint.setColor(Color.RED); // 将参考点的Paint设置为红色
        mPointPaint.setStyle(Paint.Style.STROKE);// 不填充
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

Canvas的绘图像和文字字的相关措施:

Canvas的绘图像和文字字的连带措施:

drawText()的重载方法

drawText()
是Canvas的绘图像和文字字中的最长用的法门,它不得不根据从左至右的常常情势来绘制文字。

  • drawText(String text, float x, float y, Paint paint)
  1. text:待绘制的文字内容
  2. x:文字绘制地方的x坐标
  3. y:文字绘制地方的y坐标
  4. paint:Paint画笔,能够通过Paint.setTextAlign()来调控文字的方面,有:Paint.阿里gn.LEFT(居左),Paint.Align.LacrosseIGHT(居右),Paint.Align.CENTE帕Jero(居中)多个岗位。
  • drawText(String text, int start, int end, float x, float y, Paint
    paint)
  1. start:代表从text中的第多少个字符开端截取绘制,包罗第start个字符。
  2. end:代表截取到text的第多少个字符,不含有第end个字符。

比如说:笔者是二个自定义View的控件,start=一,end=陆,截取后为:是2个自定

上面三个重载方法能够参见第1个很容易就能明白:

  • drawText(CharSequence text, int start, int end, float x, float y,
    Paint paint)
  • drawText(char[] text, int index, int count, float x, float y,
    Paint paint)

以下示例表明了文字的不如职责,同时也表明了第一个和第多个重载方法对字符串截取时的用法:

String str = "我是一个自定义View的控件";// 待绘制文字

float x = getWidth() / 2;
float y = 100;
canvas.drawPoint(x, y, mPointPaint); // 绘制参考点,便于观察文字处于x,y坐标的位置,从而来学习setTextAlign()方法

mTextPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(str, x, y, mTextPaint);

y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(str, 0, 6, x, y, mTextPaint);

y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(str.toCharArray(), 1, 6, x, y, mTextPaint);

职能图如下:

图片 23

里面包车型客车红点为额外增添的参照坐标,目的是为了卓越setTextAlign中参数的地点。

drawText()的重载方法

drawText()
是Canvas的绘图像和文字字中的最长用的不2秘诀,它只可以根据从左至右的平常格局来绘制文字。

  • drawText(String text, float x, float y, Paint paint)
  1. text:待绘制的文字内容
  2. x:文字绘制地点的x坐标
  3. y:文字绘制地点的y坐标
  4. paint:Paint画笔,能够通过Paint.setTextAlign()来决定文字的方面,有:Paint.Align.LEFT(居左),Paint.阿里gn.路虎极光IGHT(居右),Paint.Align.CENTERAV4(居中)五个岗位。
  • drawText(String text, int start, int end, float x, float y, Paint
    paint)
  1. start:代表从text中的第多少个字符早先截取绘制,包涵第start个字符。
  2. end:代表截取到text的第多少个字符,不含有第end个字符。

譬如说:我是三个自定义View的控件,start=壹,end=⑥,截取后为:是1个自定

上面四个重载方法能够参考第四个很轻巧就能领会:

  • drawText(CharSequence text, int start, int end, float x, float y,
    Paint paint)
  • drawText(char[] text, int index, int count, float x, float y,
    Paint paint)

以下示例表明了文字的例外职位,同时也表明了第三个和第多个重载方法对字符串截取时的用法:

String str = "我是一个自定义View的控件";// 待绘制文字

float x = getWidth() / 2;
float y = 100;
canvas.drawPoint(x, y, mPointPaint); // 绘制参考点,便于观察文字处于x,y坐标的位置,从而来学习setTextAlign()方法

mTextPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(str, x, y, mTextPaint);

y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(str, 0, 6, x, y, mTextPaint);

y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(str.toCharArray(), 1, 6, x, y, mTextPaint);

意义图如下:

图片 24

里头的红点为额外加多的参照坐标,目的是为了卓越setTextAlign中参数的职务。

drawTextOnPath()的重载方法

drawTextOnPath()
由艺术名字我们就能够看出来她能够依照Path的走平素绘制文字,例如大家在path中传唱1个弧形,那么绘制出来的文字走向正是圆弧状的,是还是不是很酷,来看一下它的重载方法:

  • drawTextOnPath(String text, Path path, float hOffset, float vOffset,
    Paint paint)
  1. text:同drawText的首先个参数。
  2. path:Path参数,用法在前文已经说过了。
  3. hOffset:水平方向的偏移量。
  4. vOffset:垂直方向的偏移量。

关键点:有少数早晚要提的正是,那里的hOffset是相对于path路线的程度偏移量,而vOffset也是争辩于path路线的垂直偏移量,这么说或然还多少不精晓,结合下边包车型地铁演示来声明,请仔细回味这里的情致:

// 1、下开口圆弧方向绘制文字
mTextPaint.setTextAlign(Paint.Align.LEFT);
y += Y_SPACE;
Path path = new Path();
path.addArc(new RectF(x - 150, y, x + 150, y + 300), 180,180);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint); // 按照path路径绘制文字,不偏移
canvas.drawTextOnPath(str, path, 30, 30, mTextPaint);// 向水平、垂直方向各偏移30
canvas.drawTextOnPath(str, path, 60, 60, mTextPaint);// 向水平、垂直方向各偏移60

// 2、上开口圆弧方向绘制文字
path.reset();
y += Y_SPACE;
path.addArc(new RectF(x - 150, y, x + 150, y + 300), 0, 180);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint);
canvas.drawTextOnPath(str, path, 30, 30, mTextPaint);
canvas.drawTextOnPath(str, path, 60, 60, mTextPaint);
path.close();

// 3、竖直方向绘制文字
path.reset();
path.moveTo(200, y);
path.lineTo(200, y + 4 * Y_SPACE);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint);
canvas.drawTextOnPath(str, path, 30, 60, mTextPaint);


y += Y_SPACE;
y += Y_SPACE;
y += Y_SPACE;
y += Y_SPACE;

// 4、水平方向绘制文字
path.reset();
path.moveTo(x, y);
path.lineTo(x + 4 * Y_SPACE, y);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint);
canvas.drawTextOnPath(str, path, 30, 60, mTextPaint);

正如是法力图,注意看图片中的浅橄榄黑部分,浅蓝的线是用代码绘制出来的path参考线,青灰的箭头是path的档次和垂直方向的走向,结合下图能够越来越好的敞亮drawTextOnPath的hOffset和vOffset参数。

图片 25

  • drawTextOnPath(char[] text, int index, int count, Path path, float
    hOffset, float vOffset, Paint paint)

其一法子的覆辙想必不用解释了。

drawTextOnPath()的重载方法

drawTextOnPath()
由艺术名字我们就能够看出来她能够服从Path的走一贯绘制文字,例如大家在path中传唱3个半圆,那么绘制出来的文字走向就是圆弧状的,是或不是很酷,来看一下它的重载方法:

  • drawTextOnPath(String text, Path path, float hOffset, float vOffset,
    Paint paint)
  1. text:同drawText的首先个参数。
  2. path:Path参数,用法在前文已经说过了。
  3. hOffset:水平方向的偏移量。
  4. vOffset:垂直方向的偏移量。

关键点:有有个别明显要提的正是,那里的hOffset是相持于path路线的品位偏移量,而vOffset也是相对于path路线的垂直偏移量,这么说或然还有个别不晓得,结合上边包车型大巴言传身教来验证,请密切回味那里的情趣:

// 1、下开口圆弧方向绘制文字
mTextPaint.setTextAlign(Paint.Align.LEFT);
y += Y_SPACE;
Path path = new Path();
path.addArc(new RectF(x - 150, y, x + 150, y + 300), 180,180);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint); // 按照path路径绘制文字,不偏移
canvas.drawTextOnPath(str, path, 30, 30, mTextPaint);// 向水平、垂直方向各偏移30
canvas.drawTextOnPath(str, path, 60, 60, mTextPaint);// 向水平、垂直方向各偏移60

// 2、上开口圆弧方向绘制文字
path.reset();
y += Y_SPACE;
path.addArc(new RectF(x - 150, y, x + 150, y + 300), 0, 180);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint);
canvas.drawTextOnPath(str, path, 30, 30, mTextPaint);
canvas.drawTextOnPath(str, path, 60, 60, mTextPaint);
path.close();

// 3、竖直方向绘制文字
path.reset();
path.moveTo(200, y);
path.lineTo(200, y + 4 * Y_SPACE);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint);
canvas.drawTextOnPath(str, path, 30, 60, mTextPaint);


y += Y_SPACE;
y += Y_SPACE;
y += Y_SPACE;
y += Y_SPACE;

// 4、水平方向绘制文字
path.reset();
path.moveTo(x, y);
path.lineTo(x + 4 * Y_SPACE, y);
canvas.drawPath(path, mPointPaint); // 参考弧度线
canvas.drawTextOnPath(str, path, 0, 0, mTextPaint);
canvas.drawTextOnPath(str, path, 30, 60, mTextPaint);

如下是效益图,注意看图片中的桃红部分,白色的线是用代码绘制出来的path参考线,浅黄的箭头是path的水准和垂直方向的走向,结合下图能够更加好的了然drawTextOnPath的hOffset和vOffset参数。

图片 26

  • drawTextOnPath(char[] text, int index, int count, Path path, float
    hOffset, float vOffset, Paint paint)

这些主意的套路想必不用解释了。

drawTextRun()的重载方法

  • drawTextRun(char[] text, int index, int count, int contextIndex,
    int contextCount, float x, float y, boolean isRtl, Paint paint)
  • drawTextRun(CharSequence text, int start, int end, int contextStart,
    int contextEnd, float x, float y, boolean isRtl, Paint paint)

drawTextRun()能够文字的是从左到右依旧从右到左的一1来绘制,当中尾数第四个参数is卡宴tl便是用来支配方向的,true正是倒序绘制,false正是正序绘制,别的的参数就没啥好说的了,那些方法用法比较轻巧,那里就不贴代码了。其余那么些办法是在API
二三才先河增添的,使用时要留意。

到近日结束,Canvas的常用用法基本介绍完了,接下去就能够首要来看Paint的利用了,Paint和Canvas两者是不行分离的,两者合营,相辅相成。所以在上面包车型地铁用法示例中难免要用到Canvas的相干方法。

drawTextRun()的重载方法

  • drawTextRun(char[] text, int index, int count, int contextIndex,
    int contextCount, float x, float y, boolean isRtl, Paint paint)
  • drawTextRun(CharSequence text, int start, int end, int contextStart,
    int contextEnd, float x, float y, boolean isRtl, Paint paint)

drawTextRun()能够文字的是从左到右依旧从右到左的种种来绘制,当中倒数第二个参数is昂科威tl正是用来调控方向的,true正是倒序绘制,false正是正序绘制,别的的参数就没啥好说的了,这一个主意用法比较轻松,那里就不贴代码了。此外这几个措施是在API
23才起来增添的,使用时要留心。

到近日结束,Canvas的常用用法基本介绍完了,接下去就能够重点来看Paint的运用了,Paint和Canvas两者是不行分离的,两者合作,相反相成。所以在底下的用法示例中难免要用到Canvas的连带方法。

选取Paint衡量文字的尺码,定位文字

大家在支付自定义控件时,免不了要精分明位文字的文字,例如必须把文字放在有个别区域的正中间,可能必须让1行文字的几何中央精确的处于某些点上,那时我们只要不懂那里的法门恐怕就要盲目标试位置了,那样一点一点试出来的职务很不可靠,可能换个荧屏尺寸地方就狼狈了,接下去怎么来看望哪些用最优雅的架子来规范的一贯文字。

其实在档次方向的定位还比较好说,直接使用Paint.setTextAlign()就能解决好些个必要,首假若在档次方向上稍稍复杂一点,想要定位地方,首先必要先拿到文字的中度,要用到Paint的以下五个法子:

  • float
    ascent():依据文字大小获取文字顶端到文字基线的相距(重回的是负值)
  • float
    descent():依照文字大小获取文字底部到文字基线的相距(再次回到的事正值)

有了那两个措施那就10分好办了,首先用代码结合作用图说澳优下基线、ascent、descent和文字的关系:

y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
canvas.drawLine(x - 300, y, x+300, y, mPointPaint);
mTextPaint.setTextAlign(Paint.Align.CENTER);// 水平方向上让文字居中
float ascent = mTextPaint.ascent(); // 根据文字大小获取文字顶端到文字基线的距离(返回的是负值)
float descent = mTextPaint.descent(); // 根据文字大小获取文字底部到文字基线的距离(返回的事正值)
canvas.drawLine(x - 300, y + ascent, x+300, y + ascent, mPointPaint);
canvas.drawLine(x - 300, y + descent, x+300, y + descent, mPointPaint);
canvas.drawText(str, x, y, mTextPaint);

功能图如下,它们中间的关系注意看图片里面包车型地铁印证。(注:在此地感激园友在截图中提出的1处错误,现已纠正)

图片 27

接下去就让文字的大旨落在参考试场点上:

// 将文字的中心定位在参考点上
y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
canvas.drawText(str, x, y - ascent / 2 - descent / 2, mTextPaint);

意义图如下,仔细看参考试场点(红点)和文字的职位:

图片 28

动用Paint度量文字的尺码,定位文字

大家在支付自定义控件时,免不了要精明确位文字的文字,例如必须把文字放在某些区域的正中间,只怕必须让1行文字的几何大旨规范的介乎有个别点上,那时大家如若不懂那里的技法或然就要盲目标试地点了,那样一点一点试出来的岗位很不可靠赖,恐怕换个荧屏尺寸地方就窘迫了,接下去怎么来探望如何用最优雅的姿势来规范的定点文字。

实际在档次方向的一向还比较好说,直接动用Paint.setTextAlign()就能化解大多急需,主若是在档次方向上稍稍复杂一点,想要定位地方,首先须要先得到文字的可观,要用到Paint的以下五个艺术:

  • float
    ascent():依照文字大小获取文字顶端到文字基线的偏离(重返的是负值)
  • float
    descent():依据文字大小获取文字尾部到文字基线的相距(再次回到的事正值)

有了那多少个主意那就丰硕好办了,首先用代码结合职能图说贝拉米(Bellamy)下基线、ascent、descent和文字的涉嫌:

y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
canvas.drawLine(x - 300, y, x+300, y, mPointPaint);
mTextPaint.setTextAlign(Paint.Align.CENTER);// 水平方向上让文字居中
float ascent = mTextPaint.ascent(); // 根据文字大小获取文字顶端到文字基线的距离(返回的是负值)
float descent = mTextPaint.descent(); // 根据文字大小获取文字底部到文字基线的距离(返回的事正值)
canvas.drawLine(x - 300, y + ascent, x+300, y + ascent, mPointPaint);
canvas.drawLine(x - 300, y + descent, x+300, y + descent, mPointPaint);
canvas.drawText(str, x, y, mTextPaint);

功用图如下,它们之间的涉及注意看图片里面包车型大巴评释。(注:在此间多谢园友在截图中提议的壹处错误,现已校对)

图片 29

接下去就让文字的着力落在参考试场点上:

// 将文字的中心定位在参考点上
y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
canvas.drawText(str, x, y - ascent / 2 - descent / 2, mTextPaint);

成效图如下,仔细看参考试场点(红点)和文字的地方:

图片 30

选拔Paint.setShader()(着色器)绘制渐变色

使用 setShader()
方法能够增加渐变颜色也得以应用图片作为背景,其参数是一个Shader类,传入区别的Shader子类能够兑现差别的渐变效果依然加上背景图片,其子类有弹指间二种:

  • LinearGradient:线性渐变
  • RadialGradient:放射状渐变
  • SweepGradient:扫描渐变
  • BitmapShader:增多背景图片
  • ComposeShader:多种Shader组合

下边接个Shader的子类在应用方式上都差不离,那里只用LinearGradient为例说Bellamy下,并注意对LinearGradient构造器的尾声3个参数字传送入不一致的参数对应的效益图:

/* Shader 渐变 */
y = 100;
Shader shader = new LinearGradient(x - 50, y - 80, x + 50, y + 80,
        Color.parseColor("#FFCCBB"), Color.parseColor("#FF0000"), Shader.TileMode.CLAMP);
mTextPaint.setShader(shader);
canvas.drawRect(x - 500, y - 80, x + 500, y + 80, mTextPaint);

y += 3 * Y_SPACE;
Shader shader1 = new LinearGradient(x - 50, y - 80, x + 50, y + 80,
        Color.parseColor("#FFCCBB"), Color.parseColor("#FF0000"), Shader.TileMode.REPEAT);
mTextPaint.setShader(shader1);
canvas.drawRect(x - 500, y - 80, x + 500, y + 80, mTextPaint);

y += 3 * Y_SPACE;
Shader shader2 = new LinearGradient(x - 50, y - 80, x + 50, y + 80,
        Color.parseColor("#FFCCBB"), Color.parseColor("#FF0000"), Shader.TileMode.MIRROR);
mTextPaint.setShader(shader2);
canvas.drawRect(x - 500, y - 80, x + 500, y + 80, mTextPaint);

成效图如下:

图片 31

除此之外以上那么些,Paint的用法还有繁多广大,目前半会也列不完,博主在那也不得不一得之见,感兴趣的心上人可查看官方API自行研究。


最后想说的是,本类别小说为博主对Android知识进行重新梳理,查缺补漏的就学进度,一方面是对本人忘记的事物加以复习重新精通,另壹方面相信在重新学习的经过中定会有光辉的新取得,假设你也有跟自家同样的想法,无妨关怀自身一同上学,相互探究,共同提高!

参考文献:

运用Paint.setShader()(着色器)绘制渐变色

选取 setShader()
方法能够增添渐变颜色也足以动用图片作为背景,其参数是二个Shader类,传入区别的Shader子类能够达成分裂的渐变效果照旧增添背景图片,其子类有须臾间两种:

  • LinearGradient:线性渐变
  • RadialGradient:放射状渐变
  • SweepGradient:扫描渐变
  • BitmapShader:增多背景图片
  • ComposeShader:多种Shader组合

地方接个Shader的子类在动用办法上都差不离,这里只用LinearGradient为例说Bellamy(Bellamy)下,并小心对LinearGradient构造器的末段1个参数字传送入差异的参数对应的效果图:

/* Shader 渐变 */
y = 100;
Shader shader = new LinearGradient(x - 50, y - 80, x + 50, y + 80,
        Color.parseColor("#FFCCBB"), Color.parseColor("#FF0000"), Shader.TileMode.CLAMP);
mTextPaint.setShader(shader);
canvas.drawRect(x - 500, y - 80, x + 500, y + 80, mTextPaint);

y += 3 * Y_SPACE;
Shader shader1 = new LinearGradient(x - 50, y - 80, x + 50, y + 80,
        Color.parseColor("#FFCCBB"), Color.parseColor("#FF0000"), Shader.TileMode.REPEAT);
mTextPaint.setShader(shader1);
canvas.drawRect(x - 500, y - 80, x + 500, y + 80, mTextPaint);

y += 3 * Y_SPACE;
Shader shader2 = new LinearGradient(x - 50, y - 80, x + 50, y + 80,
        Color.parseColor("#FFCCBB"), Color.parseColor("#FF0000"), Shader.TileMode.MIRROR);
mTextPaint.setShader(shader2);
canvas.drawRect(x - 500, y - 80, x + 500, y + 80, mTextPaint);

成效图如下:

图片 32

除去上述这个,Paint的用法还有繁多广大,权且半会也列不完,博主在那也不得不进行试探,感兴趣的心上人可查看官方API自行索求。


终极想说的是,本类别作品为博主对Android知识张开重新梳理,查缺补漏的读书进度,一方面是对自个儿忘记的事物加以复习重新掌握,另一方面相信在重新学习的长河中定会有远大的新得到,假使你也有跟本人同一的想法,不要紧关切本身1块读书,相互斟酌,共同升高!

参考文献:

相关文章