转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/123524086
本文出自【赵彦军的博客】
本文示例代码详见:https://gitee.com/zhaoyanjun/text-draw
画笔模式
mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充
- STROKE //描边
- FILL //填充
- FILL_AND_STROKE //描边加填充
实验代码
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(40); //为了实验效果明显,特地设置描边宽度非常大
// 描边
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(200,200,100,paint);
// 填充
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(200,500,100,paint);
// 描边加填充
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(200, 800, 100, paint);

画线条
class MyView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
private val paint = Paint()
init {
paint.color = resources.getColor(R.color.black, null) //画笔颜色
paint.isAntiAlias = true //抗锯齿
paint.strokeWidth = 30f //画笔宽度
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val startX = width / 2f
val startY = height / 2f
//画线条
canvas.drawLine(startX, startY, startX + 200, startY + 200, paint)
}
}
效果图

setStrokeCap(Paint.Cap cap)
设置线冒样式,取值有
- Cap.ROUND(圆形线冒)
- Cap.SQUARE(方形线冒)
- Paint.Cap.BUTT(无线冒)
注意:冒多出来的那块区域就是线帽!就相当于给原来的直线加上一个帽子一样,所以叫线帽

setStrokeJoin(Paint.Join join)
设置线段连接处样式,取值有:
- Join.MITER(结合处为锐角)、
- Join.Round(结合处为圆弧)、
- Join.BEVEL(结合处为直线)

画圆
canvas.drawCircle(startX, startY, 100f, paint)

画矩形
canvas.drawRect(startX, startY, startX + 100, startY + 100, paint)

画弧形
canvas.drawArc(rectF, 30f, 180f, true, paint)

其他
setStrokeWidth(float width) 设置画笔宽度
setAntiAlias(boolean aa) //抗锯齿
清空画笔样式
//清空画笔复位
reset()
源码如此:

实战-绘制圆环
效果图

class MyView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
private val paint = Paint()
private val radius = 300f
init {
paint.color = resources.getColor(R.color.black, null) //画笔颜色
paint.isAntiAlias = true //抗锯齿
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val startX = width / 2f
val startY = height / 2f
//绘制圆环
paint.color = Color.parseColor("#dddddd")
paint.strokeWidth = 30f
paint.style = Paint.Style.STROKE
canvas.drawCircle(startX, startY, radius, paint)
//绘制弧形
paint.color = Color.RED
paint.strokeCap = Paint.Cap.ROUND
val rectF = RectF(startX - radius, startY - radius, startX + radius, startY + radius)
canvas.drawArc(rectF, -90f, 225f, false, paint)
}
}
实战-圆环中绘制文字

重要的是文字居中显示。
计算文字在圆环中的居中文字,有两种方式:
- 方式一:paint.getTextBounds(content, 0, content.length, bounds)
- 方式二:val fontMetrics = paint.fontMetrics
具体示例,如下所示:
class MyView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val paint = Paint()
private val radius = 300f
init {
paint.isAntiAlias = true //抗锯齿
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val startX = width / 2f
val startY = height / 2f
//绘制圆环
paint.color = Color.parseColor("#dddddd")
paint.strokeWidth = 30f
paint.style = Paint.Style.STROKE
canvas.drawCircle(startX, startY, radius, paint)
//绘制弧形
paint.color = Color.RED
paint.strokeCap = Paint.Cap.ROUND
val rectF = RectF(startX - radius, startY - radius, startX + radius, startY + radius)
canvas.drawArc(rectF, -90f, 225f, false, paint)
//绘制文字
val content = "ababcfp"
paint.textSize = 80f
paint.style = Paint.Style.FILL
//居中绘制
paint.textAlign = Paint.Align.CENTER
//加载字体
paint.typeface = ResourcesCompat.getFont(context, R.font.fangzheng)
//获取文字的的边界,这个边界基于文字baseline
val bounds = Rect()
paint.getTextBounds(content, 0, content.length, bounds)
//获取边界的高度
val boundHeight = bounds.bottom - bounds.top
canvas.drawText(content, startX, startY + boundHeight / 2, paint)
//方式二
val fontMetrics = paint.fontMetrics
val boundHeight2 = fontMetrics.descent - fontMetrics.ascent
canvas.drawText(content, startX, startY + boundHeight2 / 2, paint)
}
}
breakText 计算文本显示长度
测量文本,如果测量的宽度超过maxWidth,则提早停止
int breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth);
int breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth);
int breakText(CharSequence text, int start, int end, boolean measureForwards,
float maxWidth, float[] measuredWidth);
//measureForwards:true则从首个字符开始测量,否则从最后一个字符开始测量
//maxWidth:可接受的最大长度
//count:绘制字符总数
//measureWidth:绘制的字符的实际宽度
案例:计算宽度为 100dp 的 TextView 能在屏幕上显示多少个字符
val textString = "今天星期一,好开心,天气真好,适合出去玩啊啊啊"
val maxWidth = dip2px(this, 100f).toFloat()
val paint = binding.text.paint
val measuredWidth = FloatArray(1)
val count = paint.breakText(textString, true, maxWidth, measuredWidth)
Log.d("yu--", "字符宽度 count:$count")
dip2px 工具方法
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
fun dip2px(context: Context, dpValue: Float): Int {
val scale = context.resources.displayMetrics.density
return (dpValue * scale + 0.5f).toInt()
}
日志输出:
D/yu--: 字符宽度 count:7
意味着 textView 宽度100dp, 一行最多显示 7个字符 。
TextUtils.ellipsize
计算 textview 显示范围,如果超出最大宽度,用省略号代替。
val text = "1234567890今天不错,星期四"
val paint = binding.tv.paint
val width = binding.tv.width.toFloat()
val result = TextUtils.ellipsize(text, paint, width, TextUtils.TruncateAt.END, false, object :TextUtils.EllipsizeCallback {
override fun ellipsized(start: Int, end: Int) {
Log.d("yu--", "ellipsized $start $end")
}
})
binding.tv.text = result
Log.d("yu--", " $result")
//日志输出
D/yu--: ellipsized 10 18
D/yu--: 1234567890…
显示效果:

本文介绍了在Android应用中使用Paint对象实现画笔模式、线条绘制、圆与矩形绘制,以及圆环中的文字排版技巧,包括strokeCap和strokeJoin设置,以及如何利用breakText和ellipsize进行文本优化。
756

被折叠的 条评论
为什么被折叠?



