文字绘制 | Android 单行,多行文字绘制

简介: 文字绘制 | Android 单行,多行文字绘制

绘制文本


文字纵向居中的算法(Y轴居中),横向居中用 Paint.Align.CENTER 即可


获取文字的上下左右位置,计算中心点,然后偏移即可:


//文字位置
aint.textAlign = Paint.Align.CENTER
//获取文字的位置信息,相对于 baseLine 的左上右下位置
paint.getTextBounds("哈哈哈", 0, "哈哈哈".length, rect)
//计算文字中点
val offset = (rect.top + rect.bottom) / 2
canvas.drawText("哈哈哈", (width / 2).toFloat(), (height / 2).toFloat() - offset, paint)


优势是:让文字非常居中,不管在任何地方。


缺点:如果文字会变动,就会导致重新计算中心点,然后文字的位置可能会发生改变,这样看起来很不舒服。


使用上线和下线,


val fontMetrics = Paint.FontMetrics()
paint.getFontMetrics(fontMetrics)
val offset = (fontMetrics.ascent + fontMetrics.descent) / 2
canvas.drawText("aaaa", (width / 2).toFloat(), (height / 2).toFloat() - offset, paint)


使用这种方式,即时文字会变,它对应的位置也不会变


让文字贴顶部


paint.getFontMetrics(fontMetrics)
val offset = (fontMetrics.ascent + fontMetrics.descent) / 2
paint.textAlign = Paint.Align.LEFT
canvas.drawText("aaaa", 0f, 0f - offset, paint)


如果文字是居左的,并且文字稍微有点大,就会发现文字无法紧贴左边,解决:


使用 getTextBounds 获取的 left 值作为偏移。这个 left 不会计算左边空白的地方。


paint.getTextBounds("aaaa", 0, "aaaa".length, rect)
paint.textSize = 150f
paint.textAlign = Paint.Align.LEFT
canvas.drawText("aaaa", -(rect.left.toFloat()), 0f, paint)


让文字绘制的时候从 负的地方开始绘制即可。


绘制多行文字


class LinsTextView : View {
    val text = "Hilt 是 Android 的依赖注入库,是基于 Dagger 。可以说 Hilt 是专门为 Andorid 打造的。" +
            "\n" +
            "\u200B Hilt 创建了一组标准的 组件和作用域。这些组件会自动集成到 Android 程序中的生命周期中。在使用的时候可以指定使用的范围,事情作用在对应的生命周期当中。" +
            "————————————————\n" +
            "版权声明:本文为CSDN博主「345丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。" +
            "原文链接:https://blog.csdn.net/baidu_40389775/article/details/107095700"
    val textPaint = TextPaint()
    lateinit var staticLayout: StaticLayout
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )
    init {
        textPaint.textSize = dp2px(15f)
    }
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
    /**
     * 4,左对齐
     * 5,文字空隙,默认为 1
     * 6,添加空隙
     * 7,纵向是否要加额外的高度
     */
        staticLayout = StaticLayout(
            text, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false
        )
    }
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        staticLayout.draw(canvas)
    }
}


绘制多行文字,根据计算换行


class LinsTextView : View {
    val text = "Hilt 是 Android 的依赖注入库,是基于 Dagger 。可以说 Hilt 是专门为 Andorid 打造的。" +
            "Hilt 创建了一组标准的 组件和作用域。这些组件会自动集成到 Android 程序中的生命周期中。在使用的时候可以指定使用的范围,事情作用在对应的生命周期当中。" +
            "版权声明:本文为CSDN博主「345丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。" +
            "原文链接:https://blog.csdn.net/baidu_40389775/article/details/107095700"
    val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    var bitmap: Bitmap
    val cutWith = floatArrayOf()
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )
    init {
        paint.textSize = dp2px(15f)
        bitmap = getAvatar(dp2px(100f))
    }
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawBitmap(bitmap, width - dp2px(100f), 100f, paint)
        /**
         * 2,是否正向绘制
         * 3,View 的宽度
         * 4,拿到截取的宽度
         * return 第一行的位置
         */
        var index = paint.breakText(text, true, width.toFloat(), cutWith)
        //绘制第一行
        canvas.drawText(text, 0, index, 0f, 50f, paint)
        //绘制第二行
        var oldIndex = index
        index = paint.breakText(
            text, index, text.length, true,
            (width - bitmap.width).toFloat(), cutWith
        )
        canvas.drawText(text, oldIndex, oldIndex + index, 0f, (50 + paint.fontSpacing), paint)
        //绘制第三行
        oldIndex = index
        index = paint.breakText(
            text, oldIndex, text.length, true,
            (width - bitmap.width).toFloat(), cutWith
        )
        canvas.drawText(text, oldIndex, oldIndex + index, 0f, (50 + (paint.fontSpacing * 2)), paint)
    }
    fun getAvatar(width: Float): Bitmap {
        val options = BitmapFactory.Options()
        //设置 true,就只会取到宽高
        options.inJustDecodeBounds = true
        //拿到宽高
        BitmapFactory.decodeResource(resources, R.drawable.avatar, options)
        //使用宽高,重新获取图片,对性能有一定好处
        options.inJustDecodeBounds = false
        options.inDensity = options.outWidth
        options.inTargetDensity = width.toInt()
        return BitmapFactory.decodeResource(resources, R.drawable.avatar, options)
    }
}


0a2653c851af460fa595bd959398a8f1.png

效果如上,如果旁边有别的东西就需要手动的换行,这种效果是使用 StaticLayout 做不到的。但是可以通过 breakText 做到。


就是获取当前行能够显示多少文字,然后在显示多少文字,接着获取下一个可以显示多少。。以此类推。


上面只是一种比较 low 的写法,能看清楚原理后,就可以通过 for 循环完成。获取到 文字的高度和底部位置,然后和图片的位置进行判断,以此确定要显示文字位置即可。


相关文章
|
2月前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
212 3
|
3月前
|
数据处理 开发工具 数据安全/隐私保护
Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路
本文探讨了Android平台上推流模块中添加文字与PNG水印的技术演进。自2015年起,为了满足应急指挥及安防领域的需求,逐步发展出三代水印技术:第一代为静态文字与图像水印;第二代实现了动态更新水印内容的能力,例如实时位置与时间信息;至第三代,则优化了数据传输效率,直接使用Bitmap对象传递水印数据至JNI层,减少了内存拷贝次数。这些迭代不仅提升了用户体验和技术效率,也体现了开发者追求极致与不断创新的精神。
|
6月前
|
自然语言处理 算法 搜索推荐
Android文字匹配度算法
【5月更文挑战第15天】
|
6月前
|
算法 前端开发 Android开发
Android文字基线Baseline算法的使用讲解,Android开发面试题
Android文字基线Baseline算法的使用讲解,Android开发面试题
Android文字基线Baseline算法的使用讲解,Android开发面试题
|
6月前
|
JSON 自然语言处理 Java
Android App开发语音处理之系统自带的语音引擎、文字转语音、语音识别的讲解及实战(超详细 附源码)
Android App开发语音处理之系统自带的语音引擎、文字转语音、语音识别的讲解及实战(超详细 附源码)
304 0
|
6月前
|
XML API Android开发
Android 自定义View 之 计时文字
Android 自定义View 之 计时文字
|
前端开发 Android开发
Android 中使用Canvas绘制文字和矩形,将结果呈现在Bitmap上
Android 中使用Canvas绘制文字和矩形,将结果呈现在Bitmap上
180 0
|
Android开发 开发者
Android自定义View之定点写文字
Android自定义View之定点写文字
|
XML JavaScript Java
Android实现加载富文本以及SpannableString、SpannableStringBuilder实现部分文字可以点击,更换颜色
Android实现加载富文本以及SpannableString、SpannableStringBuilder实现部分文字可以点击,更换颜色
|
语音技术 开发工具 Android开发
Android 离线文字转语音功能-TTS(Text To Speech)
Android 离线文字转语音功能-TTS(Text To Speech)
2158 0
Android 离线文字转语音功能-TTS(Text To Speech)