Android自定义View(二):Canvas绘制文本

一、Canvas绘制文本相关方法

Canvas里面有以下几类绘制文本的相关方法:

  1. drawText系列,此系列方法为绘制文本的常规方法
drawText(String text, float x, float y, Paint paint) 
drawText(String text, int start, int end, float x, float y, Paint paint)
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) 
  1. drawPosText系列,此系列已经被标记为Deprecated了,仅作了解。此系列方法可以把文本的每个字符绘制在特定的位置
drawPosText(char[] text, int index, int count, @Size(multiple = 2) float[] pos, Paint paint)
drawPosText(String text, @Size(multiple = 2) float[] pos, Paint paint) 
  1. drawTextOnPath系列,按照Path指定路径绘制文本
drawTextOnPath(char[] text, int index, int count, Path path,    float hOffset, float vOffset, Paint paint)
drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) 
  1. drawTextRun系列,API 23新增方法,用于绘制一些特殊语言(形状特异或者方向从右到左等)的文本,比如阿拉伯语,这个我们一般用不到 ,仅作了解。
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(MeasuredText text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, Paint paint)  

我们重点关注第一类和第三类。由于Path还没有讲到,所以本篇只讲述第一类方法。

二、文本的基准线与FontMetrics

仔细看可以发现,第一类的各个方法都包含了两个名为x和y的参数。x是绘制文本原点的横坐标,y是文本绘制的基准线。这里首先看参数y,什么是文本基准线?请看下图
在这里插入图片描述

其中红色的直线就是文本的基准线,它用于测量文本垂直方向的位置。对于特定的字体,只需要指定字体大小和基准线y坐标,就可以确定文本垂直方向的位置。
Canvas中绘制文本的时候,文本大小可以通过Paint.setTextSize进行设置。设置完文字大小后,可以通过Paint.getFontMetrics获取FontMetrics对象。FontMetrics对象包含top、ascent、descent、bottom和leading属性,除leading属性外,其余属性均为图中对应的线y坐标与基准线y坐标差值,在上为负值,在下为正值。各个属性(或者说图中各个直线)含义如下:

  • top:The maximum distance above the baseline for the tallest glyph in the font at a given text size.
  • acent:The recommended distance above the baseline for singled spaced text
  • descent:The recommended distance below the baseline for singled spaced text
  • bottom:The maximum distance below the baseline for the lowest glyph in the font at a given text size
  • leading:The recommended additional space to add between lines of text
    不太懂怎么翻译,直接贴文档解析,大家意会一下。

三、文本的对齐方式

上面说到x是绘制文本原点的横坐标,是不是就是绘制文本的第一个字符的起始坐标?看如下示例:

private val paint = Paint().apply {
    isAntiAlias = true
    strokeWidth = 5f
    color = Color.RED
}

private val textPaint = Paint().apply {
    isAntiAlias = true
    textSize = 100f
    color = Color.BLACK
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    textPaint.textAlign = Paint.Align.RIGHT
    canvas.drawText("M", 200f, 200f, textPaint)
    canvas.drawPoint(200f, 200f, paint)

    textPaint.textAlign = Paint.Align.CENTER
    canvas.drawText("M", 300f, 200f, textPaint)
    canvas.drawPoint(300f, 200f, paint)

    textPaint.textAlign = Paint.Align.LEFT
    canvas.drawText("M", 500f, 200f, textPaint)
    canvas.drawPoint(500f, 200f, paint)
}

效果:
在这里插入图片描述

可见,文本对齐方式为右对齐(Paint.Align.RIGHT)的时候,x为文本绘制的终点;居中对齐时为中点;左对齐时才是起点。
另外,细心的同学可能会发现点(x,y)和绘制的文本字符是有一定距离的。这是因为字符两侧都有一定的间隙,否则一段文本的字符就都粘在一起了。

四、Android实现在View居中绘制文本

思路:

  • 根据上文可知,水平方向居中可以使用给Paint设置文本居中对齐来实现;
  • 由于Ascent线和Descent线之间为主要的内容区域,垂直方向居中也就是View的中心点要在Ascent线和Descent线的中间,那么View中线到Bootom线的距离 = (fontMetrics.descent - fontMetrics.ascent) / 2,而基准线到Bottom线的距离为fontMetrics.bottom,所以y = height / 2f + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.bottom,其中height为View的高度
    所以实现如下:
private val paint = Paint().apply {
    isAntiAlias = true
    strokeWidth = 5f
    color = Color.RED
}

private val textPaint = Paint().apply {
    isAntiAlias = true
    textSize = 100f
    color = Color.BLACK
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    // 假定View的宽高为500px
    setMeasuredDimension(500, 500)
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    // 给View一个背景颜色
    canvas.drawColor(Color.CYAN)
    textPaint.textAlign = Paint.Align.CENTER
    val fontMetrics = textPaint.fontMetrics
    val y = height / 2f + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.bottom
    canvas.drawText("M", width / 2f, y, textPaint)
    canvas.drawPoint(width / 2f, height / 2f, paint)
}

效果:
在这里插入图片描述

另外如果要在绘制文本之前预先测量文本宽度,可以使用Paint.measureText相关方法。

五、使用字体

如果不想使用默认的字体,我们可以通过Paint.setTypeface方法来设置我们想要的字体。Android为我们预置了如下几种字体:
在这里插入图片描述
如果想使用外部字体文件,可以把目标字体文件复制到assets目录下,然后:

private val textPaint = Paint().apply {
    ...
    typeface = Typeface.createFromAsset(context.assets, "Marsboy-Regular.ttf")
}

六、其他

Android中关于绘制字体还有其他非常多的设置,比如说下划线、删除线等等。Paint还有一个TextPaint子类,针对文本提供了一些额外的设置,有兴趣的同学可以了解一下。
Android的API太多,这里无法一一列举额。我们也没有必要死记,大概知道怎么回事就行了,用到的时候看看文档或者借助百度Google搜索一下就好啦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android自定义View是指基于Android原生控件的一种扩展,可以根据自己的需求和设计规范来创建更加个性化和独特的控件。而歌词控件是一种针对音乐播放器或者视频播放器等应用场景中的需求,用于显示音乐或者视频的歌词的控件。 Android自定义View歌词控件的实现思路如下: 1. 首先需要自定义一个View,并继承自View或者其子类,如TextView。 2. 在自定义View中重写onDraw方法,在其中实现绘制歌词的逻辑。 3. 在onDraw方法中,使用Canvas对象进行绘制,可以使用drawText方法绘制歌词文本,也可以使用drawBitmap方法绘制图片背景等。 4. 可以通过自定义属性,如字体大小、字体颜色、歌词滚动速度等,来对歌词控件进行配置。 5. 如果需要实现歌词的滚动效果,可以使用ValueAnimator或者Scroller来实现歌词的平滑滚动。 6. 如果需要实现点击歌词跳转播放进度的功能,可以通过添加点击事件监听器,在触摸事件中判断点击位置对应的歌词行,并根据歌词的时间戳跳转到指定的播放进度。 总结来说,Android自定义View歌词控件的实现需要重写onDraw方法进行绘制,可以通过Canvas对象进行绘制文本或者图像,通过自定义属性进行配置,使用动画或者滚动实现歌词的平滑滚动,通过监听触摸事件实现点击歌词跳转播放进度的功能。通过以上步骤,我们可以创建一个个性化的歌词控件,满足不同应用场景的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值