从微观上提交了一个自定义View的创办步骤,从宏观上交给了一个自定义View的成立步骤

上篇小说介绍了自定义View的创建流程,从宏观上付出了1个自定义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)

此方法第②个参数是3个RectF类,也是境界,便是把3个措施的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°是指坐标系中第五象限中与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类中,剩余参数与上2个主意同样。

接下去用着三个重载方法分别绘制八个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°是指坐标系中第6象限中与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图片上截取一片段作为绘制源,可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();

效果如下图(红框内)。

图片 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]代表第3个点的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]意味着第一个点的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]意味着第6个点的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]表示第②个点的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围成的区域内绘制2个椭圆。

  • drawOval(RectF oval, Paint paint)
  1. 将第6个重载方法的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);

注:那里的rectF2即上文绘制椭圆时创设的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和drawLines一个是绘制多少个点,三个是绘制一组点,在那之中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和drawLines二个是绘制一个点,1个是绘制一组点,在那之中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方法纵然已经很强大了,不过我们如若想要绘制一些非符合规律的图纸如何是好,那时候就要用到无敌的drawPath()方法了,通过对帕特h实行安装差异的坐标、添加不相同图形,最终传入drawPath方法中得以绘制出复杂的且不规则的形状。以下是drawPath的主意及参数:

  • drawPath(Path path, Paint paint)

此间的重点参数正是Path,Path类的方法较多,大部分用法类似,这里挑多少个说一下:

  • Path类
  1. addArc(RectF oval, float startAngle, float sweepAngle)
    往path里面添加1个弧形
  2. addCircle(float x, float y, float radius, Path.Direction dir)
    添加1个圆形
  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);

意义如下图:

图片 17

再用drawPath方法绘制1个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方法纵然已经很强劲了,可是咱们如若想要绘制一些非平常的图样怎么办,那时候就要用到无敌的drawPath()方法了,通过对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个圆形
  3. addOval(RectF oval, Path.Direction dir) 添加3个椭圆
  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的用法,先来新建一个自定义类,暂叫PaintStudyView,接下去创造3个它的大体骨架,在此类中定义了一些变量,变量的意义请见注释:

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.Align.LEFT(居左),Paint.Align.LX570IGHT(居右),Paint.Align.CENTERubicon(居中)八个任务。
  • drawText(String text, int start, int end, float x, float y, Paint
    paint)
  1. start:代表从text中的第多少个字符早先截取绘制,包涵第start个字符。
  2. end:代表截取到text的第几个字符,不带有第end个字符。

比如说:笔者是二个自定义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);

效益图如下:

图片 23

中间的红点为额外添加的参阅坐标,指标是为了杰出setTextAlign中参数的岗位。

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.Align.LEFT(居左),Paint.Align.讴歌ZDXIGHT(居右),Paint.Align.CENTE安德拉(居中)四个职位。
  • drawText(String text, int start, int end, float x, float y, Paint
    paint)
  1. start:代表从text中的第多少个字符先河截取绘制,包括第start个字符。
  2. end:代表截取到text的第多少个字符,不包罗第end个字符。

诸如:笔者是三个自定义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()
由艺术名字大家就能够看出来她能够根据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参数。

图片 25

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

以此艺术的老路想必不用解释了。

drawTextOnPath()的重载方法

drawTextOnPath()
由艺术名字我们就能够看出来她可以遵循帕特h的走平昔绘制文字,例如我们在path中传唱一个弧形,那么绘制出来的文字走向正是圆弧状的,是或不是很酷,来看一下它的重载方法:

  • drawTextOnPath(String text, Path path, float hOffset, float vOffset,
    Paint paint)
  1. text:同drawText的首先个参数。
  2. path:帕特h参数,用法在前文已经说过了。
  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()能够文字的是从左到右依旧从右到左的各样来绘制,在这之中尾数第②个参数is索罗德tl正是用来支配方向的,true就是倒序绘制,false就是正序绘制,其余的参数就没啥好说的了,那个办法用法相比简单,那里就不贴代码了。别的那一个主意是在API
23才起来添加的,使用时要留意。

到近期截止,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途乐tl就是用来控制方向的,true就是倒序绘制,false正是正序绘制,其他的参数就没啥好说的了,这几个方法用法相比简单,那里就不贴代码了。此外这些法子是在API
23才起来添加的,使用时要留意。

到最近结束,Canvas的常用用法基本介绍完了,接下去就可以重点来看Paint的采取了,Paint和Canvas两者是不足分离的,两者同盟,相反相成。所以在底下的用法示例中难免要用到Canvas的连带办法。

接纳Paint度量文字的尺寸,定位文字

小编们在付出自定义控件时,免不了要精显著位文字的文字,例如必须把文字放在某些区域的正中间,也许必须让一行文字的几何中央规范的介乎有些点上,那时大家假若不懂那里的良方或然就要盲指标试地点了,那样一点一点试出来的职位很离谱赖,恐怕换个荧屏尺寸地方就窘迫了,接下去怎么来看望如何用最优雅的架势来规范的定势文字。

实则在档次方向的固化还比较好说,直接选拔Paint.setTextAlign()就能消除大多急需,首假若在档次方向上稍稍复杂一点,想要定位地点,首先须要先获得文字的中度,要用到Paint的以下七个点子:

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

有了那七个方式那就十三分好办了,首先用代码结合功用图说爱他美(Aptamil)下基线、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()
方法能够添加渐变颜色也足以接纳图片作为背景,其参数是3个Shader类,传入分裂的Shader子类可以兑现不一致的渐变效果照旧加上背景图片,其子类有眨眼之间间二种:

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

上边接个Shader的子类在运用形式上都大致,那里只用LinearGradient为例说美素佳儿(Friso)下,并注意对LinearGradient构造器的末段2个参数字传送入区别的参数对应的成效图:

/* 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()
方法能够添加渐变颜色也能够利用图片作为背景,其参数是3个Shader类,传入分化的Shader子类能够完毕差别的渐变效果仍然添加背景图片,其子类有刹那间两种:

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

地点接个Shader的子类在利用办法上都差不离,那里只用LinearGradient为例说圣元(Synutra)下,并小心对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知识展开双重梳理,查缺补漏的就学进程,一方面是对协调忘记的事物加以复习重新驾驭,另一方面相信在重新学习的进程中定会有伟大的新获得,若是您也有跟小编一样的想法,不要紧关切自笔者一同上学,相互研商,共同进步!

参考文献:

相关文章