借使把自定义View比作盖一座房屋,从细节上更进一步的上课自定义View的详尽绘制方法

上篇文章介绍了自定义View的创办流程,从宏观上付出了二个自定义View的创设步骤,本篇是上1篇文章的后续,介绍了自定义View中四个需求的工具Canvas和Paint,从细节上更进一步的任课自定义View的详实绘制方法。借使把自定义View比作盖一座房子,那么上篇小说就一定于教会了作者们怎么一步步的搭建房子的骨架,而本篇著作将要教会大家的是为房屋的骨子添砖加瓦直至成型,甚至是怎么装修。

上篇小说介绍了自定义View的成立流程,从微观上提交了二个自定义View的创造步骤,本篇是上一篇小说的接轨,介绍了自定义View中多个必备的工具Canvas和Paint,从细节上更进一步的上书自定义View的详细绘制方法。假使把自定义View比作盖1座房子,那么上篇小说就约等于教会了小编们怎么一步步的搭建房子的骨架,而本篇小说将要教会大家的是为房屋的骨子添砖加瓦直至成型,甚至是怎么装修。

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的常用方法的施用,大家先来做一些准备干活,成立3个自定义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)

此措施第1个参数是2个RectF类,也是境界,就是把一个艺术的left,top,right,bottom封装到了RectF类中,剩余参数与上多个情势一致。

接下去用着三个重载方法分别绘制四个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的第5个参数startAngle中的角度,0°是指坐标系中第伍象限中与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类,也是境界,正是把多少个方式的left,top,right,bottom封装到了RectF类中,剩余参数与上二个方法同样。

接下去用着四个重载方法分别绘制四个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°是指坐标系中第5象限中与x重合的角度,顺时针方向代表角度增大的来头,如下图中黄色线条所示。

图片 2

绘制Bitmap

在Canvas中提供了drawBitmap方法,此格局能够让大家直接获得一张图片绘制到画布上,有了它能够让大家的自定义View如鱼得水,同时也让大家贯彻部分繁杂效果有了三个尤为便于的不2秘籍。上边是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)
    同第四个重载方法,差不离一毛1样。

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

  1. matrix:Matrix的参数字传送入是的drawBitmap功用变得尤其强硬,让此办法有意思了累累,通过matrix可以完成图片的运动(postTranslate())、缩放(postScale())、旋转(postRotate())、错切(postSkew())等等花式炫酷效果,由于Matrix的用法稍微多壹些,篇幅限制,那里就先一带而过了,感兴趣的爱人能够自动探索。

在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猛虎添翼,同时也让大家落到实处部分错综复杂效果有了三个进一步惠及的门道。上面是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的用法稍微多一些,篇幅限制,那里就先一带而过了,感兴趣的情人能够自动探索。

在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数组,两位为一组,两两组合代表x、y坐标,例如:pts[0]、pts[1]代表首先个点的x、y坐标,pts[2]、pts[3]表示第二个点的x、y坐标,依次类推。
  • drawPoints(float[] pts, int offset, int count, Paint paint)
    绘制壹组点
  1. pts:float数组,两位为一组,两两重组代表x、y坐标,例如:pts[0]、pts[1]表示第四个点的x、y坐标,pts[2]、pts[3]表示第1个点的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. pts:float数组,两位为一组,两两整合代表x、y坐标,例如:pts[0]、pts[1]代表第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个点)

功效如下图:

图片 8

制图椭圆

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

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

  • drawOval(RectF oval, Paint paint)
  1. 将第三个重载方法的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围成的区域内绘制几个椭圆。

  • 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);

注:那里的rectF贰即上文绘制椭圆时成立的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不一致的是多了五个参数:

  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个是绘制3个点,叁个是绘制一组点,个中drawLines中的float数组中多少个值为一组点,其用法能够参照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和drawLines3个是绘制贰个点,八个是绘制壹组点,当中drawLines中的float数组中多个值为壹组点,其用法可以参照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方法固然已经很有力了,然则大家要是想要绘制1些有至极态的图片如何是好,那时候就要用到有力的drawPath()方法了,通过对Path举办安装分裂的坐标、添加不相同图形,最终传入drawPath方法中得以绘制出复杂的且不规则的模样。以下是drawPath的方法及参数:

  • drawPath(Path path, Paint paint)

此间的重大参数便是Path,Path类的秘诀较多,大部分用法类似,那里挑多少个说一下:

  • Path类
  1. addArc(RectF oval, float startAngle, float sweepAngle)
    往path里面添加3个圆弧
  2. addCircle(float x, float y, float radius, Path.Direction dir)
    添加2个圆形
  3. addOval(RectF oval, Path.Direction dir) 添加2个椭圆
  4. addRect(RectF rect, 帕特h.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绘制1个阶梯:

// 使用 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的叁结合特别紧密,所以讲绘制文字的不二等秘书籍放在下文和Paint1起讲可能成效会更好有的,好了,废话不多说了,接下去大家就从头Paint的小说。

drawPath() 绘制不规则图形

上边的这一个Canvas方法就算已经很有力了,可是大家只要想要绘制1些不规则的图形如何是好,那时候就要用到无敌的drawPath()方法了,通过对Path实行设置区别的坐标、添加分歧图形,最终传入drawPath方法中得以绘制出复杂的且不规则的造型。以下是drawPath的主意及参数:

  • drawPath(Path path, Paint paint)

此地的重点参数就是帕特h,Path类的不二诀窍较多,超越1/2用法类似,那里挑多少个说一下:

  • Path类
  1. addArc(RectF oval, float startAngle, float sweepAngle)
    往path里面添加1个圆弧
  2. addCircle(float x, float y, float radius, 帕特h.Direction dir)
    添加一个圆形
  3. addOval(RectF oval, Path.Direction dir) 添加3个椭圆
  4. addRect(RectF rect, Path.Direction dir) 添加1个矩形
  5. lineTo(float x, float y) 连线到坐标(x,y)
  6. moveTo(float x, float y) 将path绘制点运动到坐标(x,y)
  7. close()
    用直线闭合图形,调用此格局后,path会将最后1处点与发轫用直线连接起来,path开头点为moveTo()方法的坐标上,尽管未有调用moveTo()开头点将暗中同意为(0,0)坐标。

接下去使用drawPath绘制2个梯子:

// 使用 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的咬合特别紧凑,所以讲绘制文字的法子放在下文和Paint1起讲大概效果会更好有的,好了,废话不多说了,接下去我们就伊始Paint的作品。

Paint

为了尤其清晰的上书Paint的用法,先来新建多个自定义类,暂叫PaintStudyView,接下去创造2个它的大概骨架,在此类中定义了有个别变量,变量的含义请见注释:

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的用法,先来新建三个自定义类,暂叫PaintStudyView,接下去创造2个它的大体骨架,在此类中定义了一些变量,变量的意思请见注释:

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.setText阿里gn()来控制文字的方面,有:Paint.Align.LEFT(居左),Paint.阿里gn.酷威IGHT(居右),Paint.Align.CENTEHaval(居中)四个职务。
  • drawText(String text, int start, int end, float x, float y, Paint
    paint)
  1. start:代表从text中的第多少个字符起先截取绘制,包涵第start个字符。
  2. end:代表截取到text的第多少个字符,不含有第end个字符。

比如说:小编是一个自定义View的控件,start=一,end=6,截取后为:是多少个自定

上面五个重载方法能够参考第一个很简单就能分晓:

  • 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.Align.PAJEROIGHT(居右),Paint.Align.CENTE奥迪Q3(居中)多个任务。
  • drawText(String text, int start, int end, float x, float y, Paint
    paint)
  1. start:代表从text中的第多少个字符伊始截取绘制,包蕴第start个字符。
  2. end:代表截取到text的第多少个字符,不含有第end个字符。

例如:小编是2个自定义View的控件,start=1,end=6,截取后为:是多个自定

下边七个重载方法可以参考第一个很不难就能领略:

  • 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()
由艺术名字大家就能够看出来他得以遵守帕特h的走一向绘制文字,例如我们在path中传播一个半圆,那么绘制出来的文字走向正是圆弧状的,是否很酷,来看一下它的重载方法:

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

关键点:有1些早晚要提的正是,那里的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中盛传一个弧形,那么绘制出来的文字走向正是圆弧状的,是还是不是很酷,来看一下它的重载方法:

  • 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()能够文字的是从左到右依然从右到左的各样来绘制,其中倒数第3个参数is奥迪Q7tl正是用来控制方向的,true正是倒序绘制,false就是正序绘制,别的的参数就没啥好说的了,这几个法子用法比较简单,那里就不贴代码了。别的这么些办法是在API
贰三才起来添加的,使用时要留意。

到近年来截止,Canvas的常用用法基本介绍完了,接下去就能够主要来看Paint的利用了,Paint和Canvas两者是不足分离的,两者合营,相得益彰。所以在下边包车型大巴用法示例中难免要用到Canvas的相干办法。

使用Paint衡量文字的尺码,定位文字

小编们在付出自定义控件时,免不了要精鲜明位文字的文字,例如必须把文字放在有个别区域的正中间,可能必须让一行文字的几何宗旨规范的介乎有个别点上,那时大家若是不懂那里的奥妙大概就要盲目标试地方了,那样一点一点试出来的职务很离谱赖,只怕换个显示屏尺寸地方就难堪了,接下去怎么来看望哪些用最优雅的架势来规范的定位文字。

实际上在档次方向的向来还相比好说,间接利用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);

作用图如下,它们之间的涉嫌注意看图片里面包车型地铁表达。(注:在此间多谢园友在截图中建议的一处错误,现已校正)

图片 27

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

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

功用图如下,仔细看参考点(红点)和文字的职位:

图片 28

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

咱们在付出自定义控件时,免不了要精明确位文字的文字,例如必须把文字放在某些区域的正中间,也许必须让一行文字的几何中央规范的介乎有个别点上,那时我们若是不懂那里的门槛大概就要盲指标试地点了,那样一点一点试出来的地方很离谱,大概换个荧屏尺寸地点就难堪了,接下去怎么来看看哪些用最优雅的姿势来规范的一定文字。

实在在档次方向的定位还相比好说,直接利用Paint.setTextAlign()就能解决大多必要,主要是在档次方向上稍稍复杂一点,想要定位地点,首先必要先得到文字的冲天,要用到Paint的以下多个章程:

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

有了那三个方式那就老大好办了,首先用代码结合职能图说美赞臣下基线、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为例说澳优(Ausnutria Hyproca)(Beingmate)下,并注意对LinearGradient构造器的末梢一个参数字传送入不一致的参数对应的成效图:

/* 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为例表达一(Wissu)下,并小心对LinearGradient构造器的末尾贰个参数字传送入分裂的参数对应的效能图:

/* 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方面是对友好忘记的事物加以复习重新精晓,另壹方面相信在重新学习的长河中定会有伟大的新得到,假设你也有跟自个儿1样的想法,无妨关切本人一只念书,相互切磋,共同提高!

参考文献:

相关文章