只要在自定义控件的onDraw()中先绘制背景再绘制消息数即可,自定义控件完整代码如下:
//'自定义TextView'
open class TagTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) {
//'消息数字体大小'
var tagTextSize: Float = 0F
set(value) {
field = value
textPaint.textSize = value
}
//'消息数字体颜色'
var tagTextColor: Int = Color.parseColor("#FFFFFF")
set(value) {
field = value
textPaint.color = value
}
//'背景色'
var tagBgColor: Int = Color.parseColor("#FFFF5183")
set(value) {
field = value
bgPaint.color = value
}
//'消息数字体'
var tagTextTypeFace: Typeface? = null
//'消息数'
var tagText: String? = null
//'背景和消息数的间距'
var tagTextPaddingTop: Float = 5f
var tagTextPaddingBottom: Float = 5f
var tagTextPaddingStart: Float = 5f
var tagTextPaddingEnd: Float = 5f
//'消息数字体区域'
private var textRect: Rect = Rect()
//'消息数画笔'
private var textPaint: Paint = Paint()
//'背景画笔'
private var bgPaint: Paint = Paint()
init {
//'构建消息数画笔'
textPaint.apply {
color = tagTextColor
textSize = tagTextSize
isAntiAlias = true
textAlign = Paint.Align.CENTER
style = Paint.Style.FILL
tagTextTypeFace?.let { typeface = tagTextTypeFace }
}
//'构建背景画笔'
bgPaint.apply {
isAntiAlias = true
style = Paint.Style.FILL
color = tagBgColor
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
//'只有当消息数不为空时才绘制小红点'
tagText?.takeIf { it.isNotEmpty() }?.let { text ->
textPaint.apply {
//'1.获取消息数区域大小'
getTextBounds(text, 0, text.length, textRect)
fontMetricsInt.let {
//'背景宽=消息数区域宽+边距'
val bgWidth = (textRect.right - textRect.left) + tagTextPaddingStart + tagTextPaddingEnd
//'背景高=消息数区域高+边距'
val bgHeight = tagTextPaddingBottom + tagTextPaddingTop + it.bottom - it.top
//'取宽高中的较大值作为半径'
val radius = if (bgWidth > bgHeight) bgWidth / 2 else bgHeight / 2
val centerX = width - radius
val centerY = radius
//'2.绘制背景'
canvas?.drawCircle(centerX, centerY, radius, bgPaint)
//'3.绘制基线'
val baseline = radius + (it.bottom - it.top) / 2 - it.bottom
canvas?.drawText(text, width - radius, baseline, textPaint)
}
}
}
}
}