重学 Android 自定义 View 系列:动手实现专属 TextView

前言

前面一篇介绍了自定义View的基础概念(皮毛),接下来全部是自定义View实战,让我们一起开启自定义View之旅吧!

1. 实现目标

本篇将实现一个自定义的TextView,通过自定义属性让我们可以配置文本内容、颜色、字体大小。主要是掌握自定义View中画文字的基础概念。

  • attrs.xml 中定义自定义属性
  • 在自定义View中解析自定义属性
  • 绘制文本
  • 测量控件宽高

以下是完成效果图:

效果1:不带Padding
在这里插入图片描述
效果2:带Padding

在这里插入图片描述
看似很简单,其实有一点绕,先来看一张图。

在这里插入图片描述

首先我们需要知道一点,文字的绘制是从左下角开始的,并不是 文字左上角的坐标,这一点与其他自定义view的绘制会有一些不同,因为文字的绘制是以基线为基础的,就是上图的Baseline,当自定义Textview时,我们要么拿到确定的宽高,要么是根据文本的长度和大小去自适应宽高,不管怎样我们得到的都是一个矩形。

而我们要绘制文本,最重要的是确认基线坐标,那么基线坐标怎么获取呢?这时候就要用到 Paint.FontMetricsInt了。

Paint.FontMetricsInt 的基本概念

Paint.FontMetricsIntPaint 类中的一个内部类,用于提供字体的度量信息。它的字段主要表示从基线(baseline)到不同字符边界的距离,通常用来计算文本在垂直方向上的绘制位置。

主要字段如下:

  • top:从基线到字符最高点的距离,通常是负值。
  • ascent:从基线到字符实际顶部的距离,也是负值,但通常比 top 小。
  • descent:从基线到字符实际底部的距离,通常是正值。
  • bottom:从基线到字符最低点的距离,一般用于字符尾部的间距,是正值。
  • leading:字符之间的间距,通常用于行间距的控制。它的值可能是正的、负的或者零。

这些字段的单位通常是像素,且它们的值相对于基线来计算,如所示:

    top    --  文本框架的最高点
    ascent --  字符的最高点(字体上方留白)
    baseline -- 基线,字符绘制的参考线
    descent --  字符的最低点(字体下方留白)
    bottom  --  文本框架的最低点

这里主要用到的是 top 和 bottom。计算基线的公式如下:

     float dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
     float baseLine = getHeight() / 2 + dy;

同:

float baseLine = getHeight() / 2f - (textPaint.descent() + textPaint.ascent()) / 2f;

getHeight() / 2是控件高度的一半,(bottom - top) / 2 是字体中心与顶部的距离,用来计算从基线到中心点的位移dy。减去 bottom 是为了调整基线,使得绘制效果居中。

因为 descent 绝对值小于 ascent 所以 (textPaint.descent() + textPaint.ascent()) / 2f整体是个负值,并且为 descentascent 中点坐标,又是getHeight() / 2baseline 的偏移量,所以上面方法等同,是不是解释的不太清楚,拿笔画个图就理解了,下面那个公式确实不太好理解。下图就是草图:

在这里插入图片描述
其中 -3 位置为ascent ,2 位置为descent

(-3 + 2) / 2 = -0.5 这下理解了吧。

OK!了解了这些基础概念后,你就能画一个很正的文本了。

2. 定义自定义属性


res/values/attrs.xml 中,我们定义了三个自定义属性:xText(文本内容)、xTextColor(文本颜色)、xTextSize(文本大小)。

<declare-styleable name="MyTextView">
    <a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值