style: add GradientBorderCardView with theme-aware gradient border implementation
This commit is contained in:
parent
fcd1b0ecc5
commit
6cb45e67fc
1 changed files with 120 additions and 0 deletions
|
@ -0,0 +1,120 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.views
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.util.AttributeSet
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import androidx.preference.PreferenceManager
|
||||
|
||||
class GradientBorderCardView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : MaterialCardView(context, attrs, defStyleAttr) {
|
||||
|
||||
private val borderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
style = Paint.Style.STROKE
|
||||
strokeWidth = 6f
|
||||
}
|
||||
|
||||
private val borderPath = Path()
|
||||
private val borderRect = RectF()
|
||||
private var showGradientBorder = false
|
||||
private var isEdenTheme = false
|
||||
|
||||
init {
|
||||
setWillNotDraw(false)
|
||||
updateThemeState()
|
||||
}
|
||||
|
||||
private fun updateThemeState() {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val themeIndex = try {
|
||||
prefs.getInt(Settings.PREF_STATIC_THEME_COLOR, 0)
|
||||
} catch (e: Exception) {
|
||||
0 // Default to Eden theme if error
|
||||
}
|
||||
isEdenTheme = themeIndex == 0
|
||||
}
|
||||
|
||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||
super.onSizeChanged(w, h, oldw, oldh)
|
||||
|
||||
// Update border style based on theme
|
||||
if (isEdenTheme) {
|
||||
// Gradient for Eden theme
|
||||
borderPaint.shader = LinearGradient(
|
||||
0f, 0f,
|
||||
w.toFloat(), h.toFloat(),
|
||||
context.getColor(R.color.eden_border_gradient_start),
|
||||
context.getColor(R.color.eden_border_gradient_end),
|
||||
Shader.TileMode.CLAMP
|
||||
)
|
||||
} else {
|
||||
// Solid color for other themes
|
||||
borderPaint.shader = null
|
||||
val typedValue = android.util.TypedValue()
|
||||
context.theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue, true)
|
||||
borderPaint.color = typedValue.data
|
||||
}
|
||||
|
||||
// Update border rect with padding for stroke
|
||||
val halfStroke = borderPaint.strokeWidth / 2
|
||||
borderRect.set(
|
||||
halfStroke,
|
||||
halfStroke,
|
||||
w - halfStroke,
|
||||
h - halfStroke
|
||||
)
|
||||
|
||||
// Update path with rounded corners
|
||||
borderPath.reset()
|
||||
borderPath.addRoundRect(
|
||||
borderRect,
|
||||
radius,
|
||||
radius,
|
||||
Path.Direction.CW
|
||||
)
|
||||
}
|
||||
|
||||
override fun onFocusChanged(gainFocus: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
|
||||
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
|
||||
showGradientBorder = gainFocus
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun setSelected(selected: Boolean) {
|
||||
super.setSelected(selected)
|
||||
showGradientBorder = selected
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun setPressed(pressed: Boolean) {
|
||||
super.setPressed(pressed)
|
||||
if (pressed) {
|
||||
showGradientBorder = true
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
if (showGradientBorder && !isPressed) {
|
||||
canvas.drawPath(borderPath, borderPaint)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
updateThemeState()
|
||||
requestLayout()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue