Android自定义CircleTextView右侧被裁剪、文字不居中问题如何解决
问题根因
- 右侧裁剪:
onMeasure方法中直接对MeasureSpec原始值做大小比较,未解析MeasureSpec携带的实际尺寸和测量模式,导致View宽高计算错误,圆形超出View实际绘制区域被裁剪- 布局XML中
CircleTextView标签末尾多了冗余的/>闭合符,导致布局属性解析异常
- 文字不居中:
测量出的View不是严格正方形,gravity=center仅让文字在View矩形区域居中,和你自定义绘制的圆形中心不匹配。
修复方案
1. 修正自定义CircleTextView代码
主要修改onMeasure逻辑,正确解析测量尺寸,同时优化绘制逻辑适配多设备:
class CircleTextView(context: Context, attrs: AttributeSet) : AppCompatTextView(context, attrs) { private val circlePaint = Paint() private val strokePaint = Paint() // 描边宽度转dp适配不同屏幕密度 private val strokeWidth = 10f.dp2px(context) private fun initViews(context: Context, attrs: AttributeSet) { circlePaint.apply { color = Color.parseColor("#041421") style = Paint.Style.FILL isAntiAlias = true isDither = true } strokePaint.apply { color = Color.parseColor("#fe440b") style = Paint.Style.FILL isAntiAlias = true isDither = true } // 内置居中属性,无需额外在布局配置 gravity = Gravity.CENTER } override fun onDraw(canvas: Canvas) { // 测量后为正方形,宽高一致 val diameter = measuredWidth val radius = diameter / 2f // 绘制外圈描边 canvas.drawCircle(radius, radius, radius, strokePaint) // 绘制内圈背景 canvas.drawCircle(radius, radius, radius - strokeWidth, circlePaint) // 绘制TextView原生文字 super.onDraw(canvas) } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { // 解析两个方向的实际测量尺寸 val widthSize = MeasureSpec.getSize(widthMeasureSpec) val heightSize = MeasureSpec.getSize(heightMeasureSpec) // 取最大值作为正方形边长,确保圆形不会被裁剪 val dimension = max(widthSize, heightSize) // 强制设置为正方形尺寸 setMeasuredDimension(dimension, dimension) } // 扩展函数:dp转px private fun Float.dp2px(context: Context): Float { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, context.resources.displayMetrics) } init { initViews(context, attrs) } }
2. 修正XML布局
删除CircleTextView标签末尾冗余的闭合符:
<?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" android:background="@color/colorPrimary"> <com.example.ui.views.CircleTextView android:id="@+id/circleText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/colorWhite" android:textSize="18sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
3. Activity原有逻辑可直接复用
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_splash) circleText.apply { text = "II" setPadding(50, 50, 50, 50) } }
内容的提问来源于stack exchange,提问作者james04
相关产品推荐
相关产品推荐

