Browse Source
style: add GradientBorderCardView with theme-aware gradient border implementation
pull/49/head
style: add GradientBorderCardView with theme-aware gradient border implementation
pull/49/head
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() |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue