每次给View加shape时都要写一堆的drawable文件,不容易管理,所以封装一下。
大体效果是这样的:
可以定义的属性有5种形状(shape_type),边线颜色(shape_line_color),边线宽度(shape_line_width),圆角矩形的角度(shape_radius),是否填充中间(shape_solid),填充中间颜色(shape_solid_color,该属性在shape_solid为true时生效)。
具体代码:
<com.ycq.ycqlibrary.view.ShapeView
android:layout_width="200dp"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:gravity="center"
android:layout_marginTop="10dp"
android:text="你好,世界"
android:textSize="30sp"
app:shape_line_color="@color/purple_200"
app:shape_line_width="4dp"
app:shape_radius="4dp"
app:shape_solid="true"
app:shape_solid_color="@color/read"
app:shape_type="both_circle" />
?下边是全部的代码:
package com.ycq.ycqlibrary.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import com.ycq.ycqlibrary.R
/**
* 标签View,主要解决各种各样的View的外框
* 目前有:
* 圆角矩形 rectangle
* 圆形 circle
* 左半圆+右圆角矩形 left_circle
* 右半圆+左圆角矩形 right_circle
* 两边半圆+中间矩形 both_circle
*/
class ShapeView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
androidx.appcompat.widget.AppCompatTextView(context, attrs, defStyleAttr) {
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, -1)
constructor(context: Context) : this(context, null)
companion object {
const val rectangle = 0
const val circle = 1
const val left_circle = 2
const val right_circle = 3
const val both_circle = 4
const val default_line_width = 1f
const val default_radius = 5f
}
private var shapeType: Int = 0
private var shapeSolid: Boolean = false
private var shapeSolidColor: Int = Color.parseColor("#FFFFFF")
private var shapeLineWidth: Float = default_line_width
private var shapeLineColor: Int = Color.parseColor("#FFFFFF")
private var shapeRadius: Float = default_radius
private val paint: Paint = Paint()
private var halfLineWidth = 0f
init {
initView(context, attrs)
initPaint()
halfLineWidth = shapeLineWidth / 2
}
private fun initPaint() {
paint.apply {
isAntiAlias = true
strokeWidth = shapeLineWidth
color = shapeLineColor
//画笔样式
style = Paint.Style.STROKE
//拐角风格
strokeJoin = Paint.Join.ROUND
//笔锋样式
strokeCap = Paint.Cap.ROUND
}
}
@SuppressLint("CustomViewStyleable")
private fun initView(context: Context, attrs: AttributeSet?) {
val obtain = context.obtainStyledAttributes(attrs, R.styleable.ShapeView)
shapeType = obtain.getInt(R.styleable.ShapeView_shape_type, rectangle)
shapeSolid = obtain.getBoolean(R.styleable.ShapeView_shape_solid, false)
shapeSolidColor =
obtain.getColor(R.styleable.ShapeView_shape_solid_color, Color.parseColor("#FFFFFF"))
shapeLineWidth =
obtain.getDimension(R.styleable.ShapeView_shape_line_width, default_line_width)
shapeLineColor =
obtain.getInt(R.styleable.ShapeView_shape_line_color, Color.parseColor("#FFFFFF"))
shapeRadius = obtain.getDimension(R.styleable.ShapeView_shape_radius, default_radius)
obtain.recycle()
}
private var viewWidth = 0
private var viewHeight = 0
private var halfViewWidth = 0f
private var halfViewHeight = 0f
private var rectF: RectF = RectF(0f, 0f, 0f, 0f)
private var leftRectF: RectF = RectF(0f, 0f, 0f, 0f)
private var rightRectF: RectF = RectF(0f, 0f, 0f, 0f)
private var centerRectF: RectF = RectF(0f, 0f, 0f, 0f)
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
viewWidth = w
viewHeight = h
halfViewWidth = (viewWidth / 2).toFloat()
halfViewHeight = (viewHeight / 2).toFloat()
//圆角矩形
rectF.apply {
left = halfLineWidth
top = halfLineWidth
right = viewWidth - halfLineWidth
bottom = viewHeight - halfLineWidth
}
//画左边半圆时的矩形
leftRectF.apply {
left = halfLineWidth
top = halfLineWidth
right = viewHeight - halfLineWidth
bottom = viewHeight - halfLineWidth
}
//画右边圆时的矩形
rightRectF.apply {
left = viewWidth - halfLineWidth - viewHeight
top = halfLineWidth
right = viewWidth - halfLineWidth
bottom = viewHeight - halfLineWidth
}
//画两边圆时中间矩形
centerRectF.apply {
left = halfViewHeight - halfLineWidth
top = shapeLineWidth
right = viewWidth - halfViewHeight
bottom = viewHeight - shapeLineWidth
}
}
override fun onDraw(canvas: Canvas) {
when (shapeType) {
rectangle -> {
drawRectangle(canvas)
}
circle -> {
drawCircle(canvas)
}
left_circle -> {
drawLeftCircle(canvas)
}
right_circle -> {
drawRightCircle(canvas)
}
both_circle -> {
drawBothCircle(canvas)
}
}
super.onDraw(canvas)
}
private fun drawRectangle(canvas: Canvas) {
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
}
canvas.drawRoundRect(rectF, shapeRadius, shapeRadius, paint)
}
paint.apply {
color = shapeLineColor
style = Paint.Style.STROKE
}
canvas.drawRoundRect(rectF, shapeRadius, shapeRadius, paint)
}
private fun drawCircle(canvas: Canvas) {
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
}
canvas.drawCircle(
halfViewWidth,
halfViewWidth,
halfViewWidth - halfLineWidth,
paint
)
}
paint.apply {
color = shapeLineColor
style = Paint.Style.STROKE
}
canvas.drawCircle(
halfViewWidth,
halfViewWidth,
halfViewWidth - halfLineWidth,
paint
)
}
/**
* 先用linecolor绘制出界面,再用solidcolor绘制出界面,留出linewidth的宽度
* @param canvas Canvas
*/
private fun drawLeftCircle(canvas: Canvas) {
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
}
} else {
paint.apply {
style = Paint.Style.FILL
color = Color.parseColor("#FFFFFF")
}
}
canvas.drawCircle(
halfViewHeight,
halfViewHeight,
halfViewHeight - halfLineWidth,
paint
)
centerRectF.apply {
left = halfViewHeight
top = halfLineWidth
right = viewWidth - halfLineWidth
bottom = viewHeight - halfLineWidth
}
canvas.drawRoundRect(centerRectF, shapeRadius, shapeRadius, paint)
paint.apply {
style = Paint.Style.STROKE
color = shapeLineColor
}
canvas.drawArc(leftRectF, 90f, 180f, false, paint)
canvas.drawRoundRect(centerRectF, shapeRadius, shapeRadius, paint)
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
strokeCap = Paint.Cap.BUTT
}
} else {
paint.apply {
style = Paint.Style.FILL
color = Color.parseColor("#FFFFFF")
strokeCap = Paint.Cap.BUTT
}
}
canvas.drawLine(
halfViewHeight,
shapeLineWidth,
halfViewHeight,
viewHeight - shapeLineWidth,
paint
)
}
/**
* 先绘制填充色(整圆+圆角矩形),在绘制边线(圆弧+原件矩形),在绘制一条线,覆盖多出来的那条线
* @param canvas Canvas
*/
private fun drawRightCircle(canvas: Canvas) {
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
}
} else {
paint.apply {
style = Paint.Style.FILL
color = Color.parseColor("#FFFFFF")
}
}
canvas.drawCircle(
viewWidth - halfViewHeight,
halfViewHeight,
halfViewHeight - halfLineWidth,
paint
)
centerRectF.apply {
left = halfLineWidth
top = halfLineWidth
right = viewWidth - halfViewHeight - halfLineWidth
bottom = viewHeight - halfLineWidth
}
canvas.drawRoundRect(centerRectF, shapeRadius, shapeRadius, paint)
paint.apply {
style = Paint.Style.STROKE
color = shapeLineColor
}
canvas.drawArc(rightRectF, 270f, 180f, true, paint)
canvas.drawRoundRect(centerRectF, shapeRadius, shapeRadius, paint)
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
strokeCap = Paint.Cap.BUTT
}
} else {
paint.apply {
style = Paint.Style.FILL
color = Color.parseColor("#FFFFFF")
strokeCap = Paint.Cap.BUTT
}
}
canvas.drawLine(
viewWidth - halfViewHeight - halfLineWidth,
shapeLineWidth,
viewWidth - halfViewHeight - halfLineWidth,
viewHeight - shapeLineWidth,
paint
)
}
/**
*先绘制填充色(整圆+圆角矩形),在绘制边线(圆弧+原件矩形),在绘制一条线,覆盖多出来的那条线
* @param canvas Canvas
*/
private fun drawBothCircle(canvas: Canvas) {
if (shapeSolid) {
paint.apply {
style = Paint.Style.FILL
color = shapeSolidColor
}
canvas.drawArc(leftRectF, 90f, 180f, true, paint)
canvas.drawArc(rightRectF, 270f, 180f, true, paint)
canvas.drawRect(centerRectF, paint)
}
paint.apply {
color = shapeLineColor
style = Paint.Style.STROKE
}
canvas.drawArc(leftRectF, 90f, 180f, false, paint)
canvas.drawArc(rightRectF, 270f, 180f, false, paint)
canvas.drawLine(
halfViewHeight - halfLineWidth,
halfLineWidth,
viewWidth - halfViewHeight,
halfLineWidth,
paint
)
canvas.drawLine(
halfViewHeight - halfLineWidth,
viewHeight - halfLineWidth,
viewWidth - halfViewHeight,
viewHeight - halfLineWidth,
paint
)
}
}
<declare-styleable name="ShapeView">
<attr name="shape_type" format="enum">
<enum name="rectangle" value="0" />
<enum name="circle" value="1" />
<enum name="left_circle" value="2" />
<enum name="right_circle" value="3" />
<enum name="both_circle" value="4" />
</attr>
<attr name="shape_solid" format="boolean" />
<attr name="shape_solid_color" format="color" />
<attr name="shape_line_width" format="dimension" />
<attr name="shape_line_color" format="color" />
<attr name="shape_radius" format="dimension" />
</declare-styleable>
|