1.先看效果。
2.代码(代码直接拷贝,正常TextView使用就行)
/**
* @author: Maple
* @date: 2022/3/17
* @description:
*/
class CenterTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr) {
override fun onDraw(canvas: Canvas?) {
// 当左边Drawable的不为空时
compoundDrawables[0]?.run {
horizontalDrawable(this)
}
// 如果上边的Drawable不为空时
compoundDrawables[1]?.run {
verticalDrawable(this)
}
// 当右边Drawable的不为空时
compoundDrawables[2]?.run {
horizontalDrawable(this)
}
// 如果下边的Drawable不为空时
compoundDrawables[3]?.run {
verticalDrawable(this)
}
super.onDraw(canvas)
}
/**
* 水平方向的重绘
*/
private fun horizontalDrawable(drawable: Drawable) {
val textWidth: Float = paint.measureText(text.toString())
// 计算总宽度(文本宽度 + drawablePadding + drawableWidth) minimumWidth或者intrinsicWidth
val bodyWidth = textWidth + compoundDrawablePadding + drawable.minimumWidth
if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
//不用处理
} else {
//这里判断主要是因为每次setPadding的时候会重新执行OnDraw(),所以进行判断,避免死循环
if (paddingRight != (width - bodyWidth).toInt() / 2) {
//设置边距
setPadding(
(width - bodyWidth).toInt() / 2,
paddingTop,
(width - bodyWidth).toInt() / 2,
paddingBottom
)
}
}
}
/**
* 垂直方向的重绘
*/
private fun verticalDrawable(drawable: Drawable) {
var textHeight: Float = (paint.fontMetrics.bottom - paint.fontMetrics.top)
// var textHeight: Float = (paint.fontMetrics.descent - paint.fontMetrics.ascent)
textHeight *= lineCount
// 计算总高度(文本高度 + drawablePadding + drawableHeight)
val bodyHeight = textHeight + compoundDrawablePadding + drawable.minimumHeight
if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
//不用处理
} else {
//这里判断主要是因为每次setPadding的时候会重新执行OnDraw(),所以进行判断,避免死循环
if (paddingBottom != (height - bodyHeight).toInt() / 2) {
//设置边距
setPadding(
paddingLeft,
(height - bodyHeight).toInt() / 2,
paddingRight,
(height - bodyHeight).toInt() / 2,
)
}
}
}
}
3.测试代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<priv.maple.library_basic.view.text.CenterTextView
android:id="@+id/view1"
android:layout_width="@dimen/dp_100"
android:layout_height="wrap_content"
android:background="@drawable/btn_20c5a3_4"
android:drawableStart="@mipmap/ic_ac_play_gold_beans"
android:drawablePadding="@dimen/dp_10"
android:gravity="center"
android:paddingVertical="@dimen/dp_10"
android:text="100"
android:textColor="@color/color_f1f1f1"
android:textSize="@dimen/sp_14"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<priv.maple.library_basic.view.text.CenterTextView
android:id="@+id/view2"
android:layout_width="@dimen/dp_100"
android:layout_height="wrap_content"
android:background="@drawable/btn_20c5a3_4"
android:drawableEnd="@mipmap/ic_ac_play_gold_beans"
android:drawablePadding="@dimen/dp_10"
android:gravity="center"
android:paddingVertical="@dimen/dp_10"
android:text="100"
android:textColor="@color/color_f1f1f1"
android:textSize="@dimen/sp_14"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/view1" />
<priv.maple.library_basic.view.text.CenterTextView
android:id="@+id/view3"
android:layout_width="@dimen/dp_100"
android:layout_height="wrap_content"
android:background="@drawable/btn_20c5a3_4"
android:drawableTop="@mipmap/ic_ac_play_gold_beans"
android:drawablePadding="@dimen/dp_10"
android:gravity="center"
android:paddingVertical="@dimen/dp_10"
android:text="100"
android:textColor="@color/color_f1f1f1"
android:textSize="@dimen/sp_14"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/view2" />
<priv.maple.library_basic.view.text.CenterTextView
android:id="@+id/view4"
android:layout_width="@dimen/dp_100"
android:layout_height="wrap_content"
android:background="@drawable/btn_20c5a3_4"
android:drawableBottom="@mipmap/ic_ac_play_gold_beans"
android:drawablePadding="@dimen/dp_10"
android:gravity="center"
android:paddingVertical="@dimen/dp_10"
android:text="100"
android:textColor="@color/color_f1f1f1"
android:textSize="@dimen/sp_14"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/view3" />
</androidx.constraintlayout.widget.ConstraintLayout>
4.代码解析
逻辑是这样考虑的,首先这个是一个居中的文本加图片,那么我们只要计算出来控件的大小减去文字的大小,图片的大小,以及drawablePadding的大小,然后再除以2,这个时候的数值就是我们所要设置的Padding。然后在onDraw里面设置setPadding就可以了。
-
compoundDrawables 可以获取一个数组,这个数组共有4个值,索引分别对应了左,上,右,下的drawable。
-
measureText 测量文字的宽度。
-
textHeight 文字的高度获取-paint.fontMetrics.bottom - paint.fontMetrics.top 文字的高度获取-paint.fontMetrics.descent - paint.fontMetrics.ascent
-
compoundDrawablePadding 返回可绘制对象和文本之间的填充。也就是Xml里面的drawablePadding。
-
drawable.minimumHeight------drawable.minimumWidth 代表了drawable图片的宽度和高度。本来使用的是intrinsicWidth看过源码以后发现intrinsicWidth如果没有高度返回的是-1,minimumHeight返回的是0,这个看源码很简单。
- layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT
这里判断是因为,咱们用的是宽度过大,还要保持图片居中的TextView控件,如果说是WRAP_CONTENT那么直接使用TextView就好了。