
attrs.xml定义view的属性
<declare-styleable name="ItemTabView">
<attr name="selectedColor" format="color" />
<attr name="normalColor" format="color" />
<attr name="gradientStartColor" format="color" />
<attr name="gradientCenterColor" format="color" />
<attr name="gradientEndColor" format="color" />
<!-- 统一的文字大小 -->
<attr name="itemTextSize" format="dimension" />
<!-- 统一的文字颜色 -->
<attr name="itemTextColor" format="color" />
<!-- 统一的文字样式 -->
<attr name="itemTextStyle" format="enum">
<enum name="normal" value="0" />
<enum name="bold" value="1" />
<enum name="italic" value="2" />
<enum name="boldItalic" value="3" />
</attr>
<!-- 选中状态下的文字颜色 -->
<attr name="selectedTextColor" format="color" />
<!-- 未选中状态下的文字颜色 -->
<attr name="normalTextColor" format="color" />
<!-- 定义每个item之间距离 -->
<attr name="itemSpacing" format="dimension" />
</declare-styleable>
新建ItemTabView
class ItemTabView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var items = listOf("1", "2", "3")
private var selectedIndex = 1
private var lastY = 0f
private var scrollOffset = 0f
private val itemHeight = 100f
private val textSize = 30f
private var selectedColor = Color.BLUE
private var normalColor = Color.WHITE
private val gradientPaint = Paint(Paint.ANTI_ALIAS_FLAG)
private var gradientStartColor = Color.parseColor("#80FFFFFF")
private var gradientCenterColor = Color.parseColor("#FFFFFFFF")
private var gradientEndColor = Color.parseColor("#80FFFFFF")
private var itemTextSize = 30f
private var itemTextColor = Color.WHITE
private var itemTextStyle = Typeface.NORMAL
private var selectedTextColor = Color.BLUE
private var normalTextColor = Color.WHITE
private var itemSpacing = 0f // 默认间距为 0
init {
paint.textSize = textSize
paint.textAlign = Paint.Align.CENTER
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ItemTabView, defStyleAttr, 0)
selectedColor = typedArray.getColor(R.styleable.ItemTabView_selectedColor, selectedColor)
normalColor = typedArray.getColor(R.styleable.ItemTabView_normalColor, normalColor)
gradientStartColor = typedArray.getColor(R.styleable.ItemTabView_gradientStartColor, gradientStartColor)
gradientCenterColor = typedArray.getColor(R.styleable.ItemTabView_gradientCenterColor, gradientCenterColor)
gradientEndColor = typedArray.getColor(R.styleable.ItemTabView_gradientEndColor, gradientEndColor)
itemTextSize = typedArray.getDimension(R.styleable.ItemTabView_itemTextSize, 30f)
itemTextColor = typedArray.getColor(R.styleable.ItemTabView_itemTextColor, Color.WHITE)
itemTextStyle = typedArray.getInt(R.styleable.ItemTabView_itemTextStyle, Typeface.NORMAL)
selectedTextColor = typedArray.getColor(R.styleable.ItemTabView_selectedTextColor, Color.BLUE)
normalTextColor = typedArray.getColor(R.styleable.ItemTabView_normalTextColor, Color.WHITE)
itemSpacing = typedArray.getDimension(R.styleable.ItemTabView_itemSpacing, 0f) // 解析间距属性
paint.textSize = itemTextSize
paint.color = itemTextColor
paint.typeface = Typeface.create(paint.typeface, itemTextStyle)
typedArray.recycle()
}
fun setItems(newItems: List<String>) {
items = newItems
selectedIndex = items.size / 2
scrollOffset = 0f
invalidate()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val centerY = height / 2f
val fontMetrics = paint.fontMetrics
for (i in items.indices) {
// 计算每个 item 的位置,加入 itemSpacing
val y = centerY + (i - selectedIndex) * (itemHeight + itemSpacing) + scrollOffset
paint.color = if (i == selectedIndex) selectedTextColor else normalTextColor
if (i == selectedIndex) {
val backgroundCenterY = y + itemHeight / 2
val startX = 0f
val endX = width.toFloat()
val startY = backgroundCenterY - itemHeight / 2
val endY = backgroundCenterY + itemHeight / 2
val gradient = LinearGradient(
startX,
startY,
endX,
endY,
intArrayOf(gradientStartColor, gradientCenterColor, gradientEndColor),
floatArrayOf(0f, 0.5f, 1f),
Shader.TileMode.CLAMP
)
gradientPaint.shader = gradient
canvas.drawRect(startX, startY, endX, endY, gradientPaint)
}
val textHeight = fontMetrics.descent - fontMetrics.ascent
val textOffset = (textHeight / 2) - fontMetrics.descent
val textY = y + itemHeight / 2 + textOffset
canvas.drawText(items[i], width / 2f, textY, paint)
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> lastY = event.y
MotionEvent.ACTION_MOVE -> {
val dy = event.y - lastY
scrollOffset += dy
lastY = event.y
// 调整滚动逻辑,支持 itemSpacing
if (abs(scrollOffset) >= itemHeight + itemSpacing) {
if (scrollOffset > 0) {
if (selectedIndex > 0) selectedIndex--
} else {
if (selectedIndex < items.size - 1) selectedIndex++
}
scrollOffset %= itemHeight + itemSpacing
}
invalidate()
}
MotionEvent.ACTION_UP -> {
// 调整抬起时的逻辑,支持 itemSpacing
if (scrollOffset > (itemHeight + itemSpacing) / 2) {
if (selectedIndex > 0) selectedIndex--
} else if (scrollOffset < -(itemHeight + itemSpacing) / 2) {
if (selectedIndex < items.size - 1) selectedIndex++
}
scrollOffset = 0f
invalidate()
}
}
return true
}
fun getSelectedItem(): String {
return items[selectedIndex]
}
fun getSelectedIndex(): Int {
return selectedIndex
}
fun setItemSpacing(spacing: Float) {
itemSpacing = spacing
invalidate() // 刷新视图
}
}
使用此view
<你的view路径.ItemTabView
android:id="@+id/right2Item"
android:layout_width="200dp"
android:layout_height="200dp"
app:selectedColor="@color/blue"
app:normalColor="@color/white"
app:gradientStartColor="@color/gradient_start"
app:gradientCenterColor="@color/gradient_center"
app:gradientEndColor="@color/gradient_end"
app:itemSpacing="6dp"
app:itemTextSize="25sp"
app:itemTextStyle="bold"
app:selectedTextColor="@color/blue"
app:normalTextColor="@color/white"/>
229

被折叠的 条评论
为什么被折叠?



