上篇小说介绍了自定义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的常用方法的应用,大家先来做1些预备工作,创立一个自定义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)
- left:扇形或圆弧所占区域的左手界线x坐标
- top:扇形或圆弧所占区域的顶端界线y坐标
- right:右侧界线x坐标
- bottom:上边界线y坐标
- startAngle:扇形或圆弧的胚胎角度
- sweepAngle:扫过的角度
- userCenter:此参数能够知道为true正是画扇形,false就是画圆弧
- paint:画笔
- drawArc(RectF oval, float startAngle, float sweepAngle, boolean
useCenter, Paint paint)
此措施第三个参数是一个RectF类,也是境界,正是把三个艺术的left,top,right,bottom封装到了RectF类中,剩余参数与上2个格局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°是指坐标系中第陆象限中与x重合的角度,顺时针方向代表角度增大的大势,如下图中革命线条所示。
制图圆弧和扇形
Canvas提供drawArc()方法,通过传递分裂的参数可用来绘制圆弧和扇形,此办法有四个重载方法,详细参数如下:
- drawArc(float left, float top, float right, float bottom, float
startAngle, float sweepAngle, boolean useCenter, Paint paint)
- left:扇形或圆弧所占区域的左手界线x坐标
- top:扇形或圆弧所占区域的顶端界线y坐标
- right:左侧界线x坐标
- bottom:上面界线y坐标
- startAngle:扇形或圆弧的序幕角度
- sweepAngle:扫过的角度
- userCenter:此参数能够知道为true便是画扇形,false便是画圆弧
- 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重合的角度,顺时针方向代表角度增大的倾向,如下图中革命线条所示。
绘制Bitmap
在Canvas中提供了drawBitmap方法,此措施可以让大家直接获取一张图纸绘制到画布上,有了它能够让大家的自定义View为虎傅翼,同时也让大家兑现部分错综复杂效果有了三个一发便于的门径。上面是drawBitmap的多少个比较常用的重载方法:
- drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
- bitmap:Bitmap财富文件
- left和top:代表了图片左上角落入的地方坐标。
- top:看2
- paint:画笔
- drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
- src:在Bitmap图片上截取壹有的作为绘制源,可null
- det:将绘制指标拉伸平铺到det内定的矩形中
-
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
同第三个重载方法,大约一毛壹样。 -
drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
- 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();
职能如下图(红框内)。
绘制Bitmap
在Canvas中提供了drawBitmap方法,此措施能够让大家从来拿走一张图纸绘制到画布上,有了它能够让我们的自定义View猛虎添翼,同时也让我们兑现部分繁杂效果有了2个更为惠及的路子。上面是drawBitmap的几个相比常用的重载方法:
- drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
- bitmap:Bitmap资源文件
- left和top:代表了图片左上角落入的地点坐标。
- top:看2
- paint:画笔
- drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
- src:在Bitmap图片上截取1有个别作为绘制源,可null
- det:将绘制目的拉伸平铺到det内定的矩形中
-
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
同第一个重载方法,大致一毛壹样。 -
drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
- 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();
作用如下图(红框内)。
绘图圆形
- drawCircle(float cx, float cy, float radius, Paint paint)
- cx:圆心x坐标
- cy:圆心y坐标
- radius:半径
canvas.drawCircle(100, 700, 100, mPaint);
成效如下图:
绘图圆形
- drawCircle(float cx, float cy, float radius, Paint paint)
- cx:圆心x坐标
- cy:圆心y坐标
- radius:半径
canvas.drawCircle(100, 700, 100, mPaint);
职能如下图:
绘制点
- drawPoint(float x, float y, Paint paint)
- x:点的x坐标
- 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)
绘制壹组点
- pts:float数组,两位为一组,两两重组代表x、y坐标,例如:pts[0]、pts[1]表示首先个点的x、y坐标,pts[2]、pts[3]意味着第壹个点的x、y坐标,依次类推。
- offset:代表数组开端跳过多少个只伊始绘制点,注意那里不是指数组的下标,而是意味着跳过多少个值。
- 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个点)
功效如下图:
绘制点
- drawPoint(float x, float y, Paint paint)
- x:点的x坐标
- y:点的y坐标
- drawPoints(float[] pts, Paint paint) 绘制一组点
- pts:float数组,两位为1组,两两组合代表x、y坐标,例如:pts[0]、pts[1]代表首先个点的x、y坐标,pts[2]、pts[3]表示第一个点的x、y坐标,依次类推。
- drawPoints(float[] pts, int offset, int count, Paint paint)
绘制一组点
- pts:float数组,两位为壹组,两两整合代表x、y坐标,例如:pts[0]、pts[1]表示第2个点的x、y坐标,pts[2]、pts[3]意味着第1个点的x、y坐标,依次类推。
- offset:代表数组开头跳过多少个只先河绘制点,注意那里不是指数组的下标,而是意味着跳过几个值。
- 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个点)
效率如下图:
绘图椭圆
- drawOval(float left, float top, float right, float bottom, Paint
paint)
- left
- top
- right
- bottom
在left、top、right、bottom围成的区域内绘制多个椭圆。
- drawOval(RectF oval, Paint paint)
- 将首先个重载方法的left、top、right、bottom封装到RectF类中,与扇形的重载方法异曲同工。
RectF rectF2 = new RectF(300, 600, 700, 800); // 创建一个RectF
canvas.drawOval(rectF2, mPaint);
作用如下图:
绘制椭圆
- drawOval(float left, float top, float right, float bottom, Paint
paint)
- left
- top
- right
- bottom
在left、top、right、bottom围成的区域内绘制2个椭圆。
- drawOval(RectF oval, Paint paint)
- 将率先个重载方法的left、top、right、bottom封装到RectF类中,与扇形的重载方法异曲同工。
RectF rectF2 = new RectF(300, 600, 700, 800); // 创建一个RectF
canvas.drawOval(rectF2, mPaint);
功能如下图:
制图矩形
- 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对象。
绘制矩形
- 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对象。
绘图圆角矩形
- 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类似,唯一分歧的是多了七个参数:
- rx:x轴方向的圆角弧度
- ry:y轴方向的圆角弧度
上代码,看效果:
canvas.drawRoundRect(rectF2, 60, 30, mPaint);
此地为了卓越多少个趋势的圆角弧度,特地将rx和ry设置差异比较大,效果如下图:
制图圆角矩形
- 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类似,唯一分歧的是多了多个参数:
- rx:x轴方向的圆角弧度
- ry:y轴方向的圆角弧度
上代码,看效果:
canvas.drawRoundRect(rectF2, 60, 30, mPaint);
那边为了突出五个样子的圆角弧度,特地将rx和ry设置差别比较大,效果如下图:
绘制直线
- 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组,绘制多条线
职能如下图:
绘制直线
- 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数组中几个值为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组,绘制多条线
功能如下图:
drawPath() 绘制不规则图形
上边的那个Canvas方法纵然已经很强劲了,但是大家只要想要绘制一些非正常的图形怎么做,那时候就要用到无敌的drawPath()方法了,通过对Path进行设置差异的坐标、添加分裂图形,最后传入drawPath方法中得以绘制出复杂的且不规则的形制。以下是drawPath的章程及参数:
- drawPath(Path path, Paint paint)
此间的机要参数正是Path,Path类的方法较多,大多数用法类似,那里挑多少个说一下:
- Path类
- 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) 添加3个椭圆
- addRect(RectF rect, Path.Direction dir) 添加一个矩形
- lineTo(float x, float y) 连线到坐标(x,y)
- moveTo(float x, float y) 将path绘制点运动到坐标(x,y)
- close()
用直线闭合图形,调用此形式后,path会将最后一处点与开端用直线连接起来,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);
效益如下图:
再用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);
成效图如下:
最终,上文中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);
}
}
全体意义图如下:
其实Canvas除了能够绘制图形之外,还足以绘制文字,Canvas的绘图文字的法子有drawText()、drawTextOnPath()、drawTextRun()等形式,在绘制文字是和Paint的重组愈加严峻,所以讲绘制文字的点子放在下文和Paint一起讲或然效果会更好一些,好了,废话不多说了,接下去大家就从头Paint的稿子。
drawPath() 绘制不规则图形
上边的那些Canvas方法尽管已经很强劲了,可是大家假设想要绘制一些难堪的图形咋办,那时候就要用到有力的drawPath()方法了,通过对Path进行安装不一致的坐标、添加不相同图形,最终传入drawPath方法中得以绘制出复杂的且不规则的形态。以下是drawPath的不2诀窍及参数:
- drawPath(Path path, Paint paint)
那边的重大参数便是Path,Path类的办法较多,大多数用法类似,那里挑多少个说一下:
- Path类
- addArc(RectF oval, float startAngle, float sweepAngle)
往path里面添加四个半圆 - addCircle(float x, float y, float radius, Path.Direction dir)
添加三个圆形 - addOval(RectF oval, Path.Direction dir) 添加二个椭圆
- addRect(RectF rect, Path.Direction dir) 添加3个矩形
- lineTo(float x, float y) 连线到坐标(x,y)
- moveTo(float x, float y) 将path绘制点运动到坐标(x,y)
- close()
用直线闭合图形,调用此方式后,path会将最后1处点与开端用直线连接起来,path初步点为moveTo()方法的坐标上,若是未有调用moveTo()起先点将默许为(0,0)坐标。 - …
接下去使用draw帕特h绘制一个楼梯:
// 使用 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);
功能如下图:
再用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);
效用图如下:
末尾,上文中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);
}
}
完整意义图如下:
实际上Canvas除了能够绘制图形之外,还足以绘制文字,Canvas的绘图像和文字字的点子有drawText()、drawTextOnPath()、drawTextRun()等艺术,在绘制文字是和Paint的组成愈加严刻,所以讲绘制文字的秘籍放在下文和Paint一起讲或者效果会更好一些,好了,废话不多说了,接下去大家就起来Paint的篇章。
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);
}
}
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);
}
}
Canvas的绘图像和文字字的相干措施:
Canvas的绘图文字的连带办法:
drawText()的重载方法
drawText()
是Canvas的绘图像和文字字中的最长用的法子,它只好依据从左至右的常见格局来绘制文字。
- drawText(String text, float x, float y, Paint paint)
- text:待绘制的文字内容
- x:文字绘制地点的x坐标
- y:文字绘制地点的y坐标
- paint:Paint画笔,能够通过Paint.setTextAlign()来控制文字的方向,有:Paint.Align.LEFT(居左),Paint.阿里gn.ENCOREIGHT(居右),Paint.Align.CENTERAV四(居中)四个岗位。
- drawText(String text, int start, int end, float x, float y, Paint
paint)
- start:代表从text中的第多少个字符开头截取绘制,包蕴第start个字符。
- end:代表截取到text的第多少个字符,不带有第end个字符。
比如:笔者是三个自定义View的控件,start=1,end=6,截取后为:是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)
以下示例表明了文字的不等职位,同时也验证了第2个和第几个重载方法对字符串截取时的用法:
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);
成效图如下:
个中的红点为额外添加的参照坐标,指标是为了特出setTextAlign中参数的任务。
drawText()的重载方法
drawText()
是Canvas的绘图像和文字字中的最长用的法子,它不得不遵照从左至右的家常格局来绘制文字。
- drawText(String text, float x, float y, Paint paint)
- text:待绘制的文字内容
- x:文字绘制地点的x坐标
- y:文字绘制地方的y坐标
- paint:Paint画笔,能够通过Paint.setTextAlign()来决定文字的方位,有:Paint.Align.LEFT(居左),Paint.Align.奥迪Q7IGHT(居右),Paint.Align.CENTEHummerH贰(居中)八个岗位。
- drawText(String text, int start, int end, float x, float y, Paint
paint)
- start:代表从text中的第几个字符初阶截取绘制,包涵第start个字符。
- end:代表截取到text的第几个字符,不蕴涵第end个字符。
诸如:笔者是3个自定义View的控件,start=一,end=陆,截取后为:是多个自定
下边多个重载方法能够参照第一个很简单就能明了:
- 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);
功能图如下:
其间的红点为额外添加的参阅坐标,目标是为着优秀setTextAlign中参数的职责。
drawTextOnPath()的重载方法
drawTextOnPath()
由艺术名字大家就能够看出来他能够遵循帕特h的走一贯绘制文字,例如大家在path中传唱1个弧形,那么绘制出来的文字走向正是圆弧状的,是否很酷,来看一下它的重载方法:
- drawTextOnPath(String text, Path path, float hOffset, float vOffset,
Paint paint)
- text:同drawText的第二个参数。
- path:Path参数,用法在前文已经说过了。
- hOffset:水平方向的偏移量。
- 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参数。
- 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)
- text:同drawText的首先个参数。
- path:Path参数,用法在前文已经说过了。
- hOffset:水平方向的偏移量。
- 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);
1般来说是意义图,注意看图片中的银色部分,高粱红的线是用代码绘制出来的path参考线,影青的箭头是path的品位和垂直方向的走向,结合下图能够更好的知晓drawTextOnPath的hOffset和vOffset参数。
- 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陆风X8tl便是用来控制方向的,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()能够文字的是从左到右照旧从右到左的1一来绘制,个中尾数第三个参数isPAJEROtl正是用来决定方向的,true正是倒序绘制,false便是正序绘制,其余的参数就没啥好说的了,这些法子用法相比简单,那里就不贴代码了。此外这些办法是在API
二3才开端添加的,使用时要留意。
到近日甘休,Canvas的常用用法基本介绍完了,接下去就足以重点来看Paint的应用了,Paint和Canvas两者是不行分离的,两者合营,相得益彰。所以在底下的用法示例中难免要用到Canvas的相关方法。
采纳Paint衡量文字的尺寸,定位文字
大家在支付自定义控件时,免不了要精明确位文字的文字,例如必须把文字放在有个别区域的正中间,或然必须让壹行文字的几何中央规范的处于有些点上,那时我们假使不懂这里的技法只怕就要盲指标试地点了,那样一点一点试出来的岗位很离谱赖,恐怕换个显示屏尺寸地方就狼狈了,接下去怎么来探望怎么样用最优雅的姿势来规范的定点文字。
实在在档次方向的一定还相比好说,直接动用Paint.setTextAlign()就能化解大多供给,首就算在档次方向上稍稍复杂一点,想要定位地方,首先必要先获得文字的惊人,要用到Paint的以下三个措施:
- float
ascent():依照文字大小获取文字顶端到文字基线的偏离(重临的是负值) - float
descent():依照文字大小获取文字尾巴部分到文字基线的偏离(重返的事正值)
有了这么些格局那就不行好办了,首先用代码结合功效图说美素佳儿(Friso)下基线、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处错误,现已勘误)
接下去就让文字的主导落在参考试场点上:
// 将文字的中心定位在参考点上
y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
canvas.drawText(str, x, y - ascent / 2 - descent / 2, mTextPaint);
成效图如下,仔细看参考试场点(红点)和文字的职位:
利用Paint度量文字的尺寸,定位文字
我们在支付自定义控件时,免不了要精分明位文字的文字,例如必须把文字放在有些区域的正中间,也许必须让1行文字的几何主题规范的介乎有个别点上,那时我们借使不懂那里的奥妙也许就要盲指标试地方了,那样一点一点试出来的岗位很不可相信,恐怕换个显示屏尺寸地点就难堪了,接下去怎么来看看哪些用最优雅的姿势来规范的定位文字。
实质上在档次方向的平昔还比较好说,直接运用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);
功用图如下,它们中间的涉及注意看图片里面包车型地铁表达。(注:在此地多谢园友在截图中建议的1处错误,现已纠正)
接下去就让文字的为主落在参考点上:
// 将文字的中心定位在参考点上
y += Y_SPACE;
canvas.drawPoint(x, y, mPointPaint);
canvas.drawText(str, x, y - ascent / 2 - descent / 2, mTextPaint);
职能图如下,仔细看参考试场点(红点)和文字的职位:
动用Paint.setShader()(着色器)绘制渐变色
利用 setShader()
方法能够添加渐变颜色也足以采取图片作为背景,其参数是三个Shader类,传入差别的Shader子类能够完毕差异的渐变效果照旧添加背景图片,其子类有瞬间两种:
- LinearGradient:线性渐变
- RadialGradient:放射状渐变
- SweepGradient:扫描渐变
- BitmapShader:添加背景图片
- ComposeShader:多种Shader组合
上面接个Shader的子类在应用格局上都大约,那里只用LinearGradient为例说美赞臣下,并注意对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);
作用图如下:
除开上述那么些,Paint的用法还有好多居多,临时半会也列不完,博主在那也不得不投石问路,感兴趣的爱人可查看官方API自行探索。
终极想说的是,本体系小说为博主对Android知识进行重复梳理,查缺补漏的就学进度,1方面是对自身忘记的事物加以复习重新精通,另一方面相信在重新学习的进度中定会有高大的新获得,若是你也有跟自个儿壹样的想法,无妨关怀本人叁头读书,互相研商,共同提高!
参考文献:
- *Android Developers:https://developer.android.com/index.html*
运用Paint.setShader()(着色器)绘制渐变色
使用 setShader()
方法能够添加渐变颜色也得以应用图片作为背景,其参数是二个Shader类,传入区别的Shader子类能够完成区别的渐变效果照旧添加背景图片,其子类有眨眼之间间二种:
- LinearGradient:线性渐变
- RadialGradient:放射状渐变
- SweepGradient:扫描渐变
- BitmapShader:添加背景图片
- ComposeShader:多种Shader组合
上边接个Shader的子类在采用方法上都大致,那里只用LinearGradient为例说宾博下,并留意对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);
效果图如下:
除了上述这一个,Paint的用法还有为数不少广大,近年来半会也列不完,博主在那也只可以投砾引珠,感兴趣的情侣可查看官方API自行探索。
末了想说的是,本种类小说为博主对Android知识进行再度梳理,查缺补漏的求学进程,一方面是对友好忘记的事物加以复习重新通晓,另1方面相信在重新学习的进度中定会有大侠的新收获,固然你也有跟本人同样的想法,无妨关怀自作者一起上学,互相研商,共同提高!
参考文献:
- *Android Developers:https://developer.android.com/index.html*