Canvas实现图文排版
文章目录
前言
沉默之后的爆发是最恐怖的
一、效果图
二、利用breakText可以获取当前宽度最多画多少个字
//计算当前的画笔最多能写多少个字
count = textPaint.breakText(msg, startCount, msg.length, true, maxWidth, measureWidth)
三、利用FontMetrics可以拿到当前画笔的top、ascent、descent、bottom、leading,由此可算出一行的高度
maxWidth =
//判断当前的高度是不是小于图片的marginTop或者大于图片高度+marginTop
if (offset + fontMetrics.bottom < 60f.px || offset + fontMetrics.top > IMAGE_SIZE+60f.px) {
//直接写完全屏
width.toFloat()
} else {
//只能写到图片的左边
width - IMAGE_SIZE
}
四、完整代码
package com.jbh.study.widget
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import com.jbh.study.R
import com.jbh.study.ext.px
import kotlin.math.max
/**
* @author bingHao.Ji
* @date 2021/8/19.
* description:
*/
class MultiTextView : View {
val msg: String =
"汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。春寒赐浴华清池,温泉水滑洗凝脂。侍儿扶起娇无力,始是新承恩泽时。云鬓花颜金步摇,芙蓉帐暖度春宵。春宵苦短日高起,从此君王不早朝。承欢侍宴无闲暇,春从春游夜专夜。后宫佳丽三千人,三千宠爱在一身。金屋妆成娇侍夜,玉楼宴罢醉和春。姊妹弟兄皆列土,可怜光彩生门户。遂令天下父母心,不重生男重生女。骊宫高处入青云,仙乐风飘处处闻。缓歌慢舞凝丝竹,尽日君王看不足。渔阳鼙鼓动地来,惊破霓裳羽衣曲。九重城阙烟尘生,千乘万骑西南行。翠华摇摇行复止,西出都门百余里。六军不发无奈何,宛转蛾眉马前死。花钿委地无人收,翠翘金雀玉搔头。君王掩面救不得,回看血泪相和流。黄埃散漫风萧索,云栈萦纡登剑阁。峨嵋山下少人行,旌旗无光日色薄。蜀江水碧蜀山青,圣主朝朝暮暮情。行宫见月伤心色,夜雨闻铃肠断声。 天旋地转回龙驭,到此踌躇不能去。马嵬坡下泥土中,不见玉颜空死处。"
val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
textSize = 18f.px
}
val fontMetrics = Paint.FontMetrics()
val IMAGE_SIZE = 100f.px
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun onDraw(canvas: Canvas) {
//绘制图片
canvas.drawBitmap(
getAvatarBitmap(IMAGE_SIZE.toInt()),
width - IMAGE_SIZE,
60f.px,
textPaint
)
//根据当前画笔拿到fontMetrics的top和bottom
textPaint.getFontMetrics(fontMetrics)
val measureWidth = floatArrayOf(0f)
var startCount = 0
var count: Int
var offset = -fontMetrics.top
var maxWidth: Float
while (startCount < msg.length) {
maxWidth =
//判断当前的高度是不是小于图片的marginTop或者大于图片高度+marginTop
if (offset + fontMetrics.bottom < 60f.px || offset + fontMetrics.top > IMAGE_SIZE+60f.px) {
//直接写完全屏
width.toFloat()
} else {
//只能写到图片的左边
width - IMAGE_SIZE
}
//计算当前的画笔最多能写多少个字
count = textPaint.breakText(msg, startCount, msg.length, true, maxWidth, measureWidth)
//画出对应的文字
canvas.drawText(msg, startCount, startCount + count, 0f, offset, textPaint)
startCount += count
offset += textPaint.fontSpacing
}
}
private fun getAvatarBitmap(width: Int): Bitmap {
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeResource(resources, R.mipmap.zzt, options)
options.inJustDecodeBounds = false
options.inDensity = options.outWidth
options.inTargetDensity = width
return BitmapFactory.decodeResource(resources, R.mipmap.zzt, options)
}
}