求助:实现带底部矩形的Circular Textview
没问题!我帮你实现这个带底部矩形的圆形TextView,下面是完整的解决方案:
实现带底部矩形的圆形TextView
1. 定义自定义属性
先在res/values/attrs.xml里添加自定义属性,方便在布局里灵活配置颜色和尺寸:
<resources> <declare-styleable name="CircularBottomRectTextView"> <!-- 圆形背景颜色 --> <attr name="circleBackgroundColor" format="color" /> <!-- 底部矩形颜色 --> <attr name="bottomRectColor" format="color" /> <!-- 底部矩形高度 --> <attr name="bottomRectHeight" format="dimension" /> <!-- 圆形内边距,避免文本贴边 --> <attr name="circlePadding" format="dimension" /> </declare-styleable> </resources>
2. 实现自定义TextView
创建CircularBottomRectTextView类,继承自AppCompatTextView,处理测量和绘制逻辑:
import android.content.Context import android.content.res.TypedArray import android.graphics.Canvas import android.graphics.Paint import android.graphics.RectF import android.util.AttributeSet import androidx.appcompat.widget.AppCompatTextView class CircularBottomRectTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.textViewStyle ) : AppCompatTextView(context, attrs, defStyleAttr) { // 绘制用的画笔 private val circlePaint = Paint(Paint.ANTI_ALIAS_FLAG) private val rectPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 自定义属性默认值 private var circleBgColor = 0xFFE0E0E0.toInt() private var bottomRectColor = 0xFF2196F3.toInt() private var bottomRectHeight = 20f // 默认20dp private var circlePadding = 16f // 默认16dp // 底部矩形的绘制区域 private val rectF = RectF() init { // 加载布局中设置的自定义属性 val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircularBottomRectTextView) circleBgColor = typedArray.getColor(R.styleable.CircularBottomRectTextView_circleBackgroundColor, circleBgColor) bottomRectColor = typedArray.getColor(R.styleable.CircularBottomRectTextView_bottomRectColor, bottomRectColor) bottomRectHeight = typedArray.getDimension(R.styleable.CircularBottomRectTextView_bottomRectHeight, dpToPx(bottomRectHeight)) circlePadding = typedArray.getDimension(R.styleable.CircularBottomRectTextView_circlePadding, dpToPx(circlePadding)) typedArray.recycle() // 初始化画笔颜色 circlePaint.color = circleBgColor rectPaint.color = bottomRectColor // 设置文本居中显示 gravity = android.view.Gravity.CENTER // 设置内边距,避免文本贴圆形边缘或被底部矩形遮挡 setPadding(circlePadding.toInt(), circlePadding.toInt(), circlePadding.toInt(), (circlePadding + bottomRectHeight).toInt()) } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) // 确保圆形区域是正方形,总高度加上底部矩形的高度 val circleSize = measuredWidth.coerceAtMost(measuredHeight) setMeasuredDimension(circleSize, (circleSize + bottomRectHeight).toInt()) } override fun onDraw(canvas: Canvas) { // 1. 先绘制圆形背景 val circleCenterX = width / 2f val circleCenterY = (height - bottomRectHeight) / 2f val circleRadius = width / 2f canvas.drawCircle(circleCenterX, circleCenterY, circleRadius, circlePaint) // 2. 绘制底部矩形 rectF.set(0f, height - bottomRectHeight, width.toFloat(), height.toFloat()) canvas.drawRect(rectF, rectPaint) // 3. 最后绘制文本,保证文本在最上层 super.onDraw(canvas) } // dp转px工具方法 private fun dpToPx(dp: Float): Float { return dp * resources.displayMetrics.density } }
3. 在布局中使用
现在可以在XML布局里直接引用这个自定义View,按需配置属性:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <com.yourpackage.CircularBottomRectTextView android:layout_width="120dp" android:layout_height="wrap_content" android:text="参考文本" android:textColor="#FFFFFF" android:textSize="18sp" app:circleBackgroundColor="#FF9800" app:bottomRectColor="#E64A19" app:bottomRectHeight="15dp" app:circlePadding="12dp" /> </LinearLayout>
关键说明
- 测量逻辑:通过
onMeasure把圆形区域强制调整为正方形,总高度加上底部矩形的高度,确保圆形和矩形都能完整显示。 - 绘制顺序:先画圆形、再画矩形、最后画文本,保证文本始终在最上层不被遮挡。
- 内边距适配:预留了圆形内边距,同时底部内边距包含了矩形高度,避免文本和矩形重叠。
你可以根据自己的需求调整颜色、尺寸等属性,完全匹配你想要的效果!
内容的提问来源于stack exchange,提问作者Aditya Hari Kishan
相关产品推荐
相关产品推荐

