feat: 弃牌堆/摸牌堆1.8倍放大,手牌区高度可调0~240dp默认160dp
This commit is contained in:
parent
570d96c5c0
commit
807976ca51
@ -70,6 +70,8 @@ fun UnoApp() {
|
||||
var cardTheme by remember { mutableStateOf(CardTheme.load(context)) }
|
||||
var tableBg by remember { mutableStateOf(TableBg.load(context)) }
|
||||
var isLandscape by remember { mutableStateOf(prefs.getBoolean("landscape", false)) }
|
||||
var cardScale by remember { mutableStateOf(loadCardScale(context)) }
|
||||
var handOffset by remember { mutableStateOf(loadHandOffset(context)) }
|
||||
|
||||
// Apply orientation on start
|
||||
LaunchedEffect(Unit) {
|
||||
@ -192,7 +194,8 @@ fun UnoApp() {
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalCardTheme provides cardTheme,
|
||||
LocalTableBg provides tableBg
|
||||
LocalTableBg provides tableBg,
|
||||
LocalCardScale provides cardScale
|
||||
) {
|
||||
val enterAnim: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition) = {
|
||||
fadeIn(animationSpec = tween(300)) + slideInHorizontally(animationSpec = tween(350)) { it / 4 }
|
||||
@ -401,6 +404,7 @@ fun UnoApp() {
|
||||
totalPlayers = totalPlayers,
|
||||
humanPlayerName = humanPlayerName,
|
||||
botNames = botNames,
|
||||
handOffset = handOffset,
|
||||
onBackToMenu = {
|
||||
navController.navigate(Screen.MainMenu.route) {
|
||||
popUpTo(0) { inclusive = true }
|
||||
@ -423,6 +427,7 @@ fun UnoApp() {
|
||||
currentTheme = cardTheme,
|
||||
currentBg = tableBg,
|
||||
isLandscape = isLandscape,
|
||||
handOffset = handOffset,
|
||||
onNameChanged = { name ->
|
||||
savedName = name
|
||||
prefs.edit().putString("player_name", name).apply()
|
||||
@ -435,6 +440,10 @@ fun UnoApp() {
|
||||
tableBg = bg
|
||||
TableBg.save(context, bg)
|
||||
},
|
||||
onSetHandOffset = { offset ->
|
||||
handOffset = offset
|
||||
saveHandOffset(context, offset)
|
||||
},
|
||||
onToggleOrientation = {
|
||||
isLandscape = !isLandscape
|
||||
prefs.edit().putBoolean("landscape", isLandscape).apply()
|
||||
|
||||
@ -16,6 +16,7 @@ import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Popup
|
||||
@ -32,21 +33,25 @@ fun CardView(
|
||||
selected: Boolean = false,
|
||||
playable: Boolean = true,
|
||||
theme: CardTheme = LocalCardTheme.current,
|
||||
scale: Float = LocalCardScale.current,
|
||||
onClick: () -> Unit = {}
|
||||
) {
|
||||
val cardBg = getCardBgColor(card.color.name)
|
||||
val isWild = card.color == CardColor.WILD
|
||||
var showInfo by remember { mutableStateOf(false) }
|
||||
val w = (60 * scale).dp
|
||||
val h = (90 * scale).dp
|
||||
val off = (-30 * scale).dp
|
||||
|
||||
Box {
|
||||
when (theme) {
|
||||
CardTheme.CLASSIC -> ClassicCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.ELEGANT -> ElegantCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.MIDNIGHT -> MidnightCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.NEON -> NeonCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.PASTEL -> PastelCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.FOREST -> ForestCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.OCEAN -> OceanCard(card, cardBg, isWild, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.CLASSIC -> ClassicCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.ELEGANT -> ElegantCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.MIDNIGHT -> MidnightCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.NEON -> NeonCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.PASTEL -> PastelCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.FOREST -> ForestCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
CardTheme.OCEAN -> OceanCard(card, cardBg, isWild, w, h, off, modifier, selected, playable, onClick, onLongPress = { showInfo = true })
|
||||
}
|
||||
|
||||
if (showInfo) {
|
||||
@ -59,13 +64,13 @@ fun CardView(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun ClassicCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 8.dp else 2.dp, RoundedCornerShape(10.dp))
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(
|
||||
@ -82,14 +87,14 @@ private fun ClassicCard(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun ElegantCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
val borderColor = if (isWild) GoldAccent else cardBg.copy(alpha = 0.5f)
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 8.dp else 3.dp, RoundedCornerShape(14.dp))
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
.background(Color.White)
|
||||
@ -122,14 +127,14 @@ private fun ElegantCard(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun MidnightCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
val glow = if (isWild) Color.Magenta.copy(alpha = 0.6f) else cardBg.copy(alpha = 0.6f)
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 12.dp else 4.dp, RoundedCornerShape(12.dp), ambientColor = glow, spotColor = glow)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(DarkCard)
|
||||
@ -153,14 +158,14 @@ private fun MidnightCard(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun NeonCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
val neonColor = if (isWild) Color.Magenta else cardBg
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 10.dp else 4.dp, RoundedCornerShape(8.dp), ambientColor = neonColor, spotColor = neonColor)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(Color(0xFF0A0A0A))
|
||||
@ -182,13 +187,13 @@ private fun NeonCard(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun PastelCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 6.dp else 2.dp, RoundedCornerShape(16.dp))
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(
|
||||
@ -218,13 +223,13 @@ private fun PastelCard(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun ForestCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 6.dp else 2.dp, RoundedCornerShape(6.dp))
|
||||
.clip(RoundedCornerShape(6.dp))
|
||||
.background(
|
||||
@ -243,13 +248,13 @@ private fun ForestCard(
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun OceanCard(
|
||||
card: Card, cardBg: Color, isWild: Boolean,
|
||||
card: Card, cardBg: Color, isWild: Boolean, w: Dp, h: Dp, off: Dp,
|
||||
modifier: Modifier, selected: Boolean, playable: Boolean, onClick: () -> Unit, onLongPress: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.width(60.dp).height(90.dp)
|
||||
.then(if (selected) Modifier.offset(y = (-30).dp) else Modifier)
|
||||
.width(w).height(h)
|
||||
.then(if (selected) Modifier.offset(y = off) else Modifier)
|
||||
.shadow(if (selected) 6.dp else 3.dp, RoundedCornerShape(10.dp))
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(
|
||||
@ -351,11 +356,13 @@ private fun CardContent(card: Card, isWild: Boolean) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.current) {
|
||||
fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.current, scale: Float = LocalCardScale.current) {
|
||||
val w = (60 * scale).dp
|
||||
val h = (90 * scale).dp
|
||||
when (theme) {
|
||||
CardTheme.CLASSIC -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(2.dp, RoundedCornerShape(10.dp))
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(DarkCard)
|
||||
@ -371,7 +378,7 @@ fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.cu
|
||||
}
|
||||
CardTheme.ELEGANT -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(3.dp, RoundedCornerShape(14.dp))
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
.background(Color.White)
|
||||
@ -386,7 +393,7 @@ fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.cu
|
||||
}
|
||||
CardTheme.MIDNIGHT -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(4.dp, RoundedCornerShape(12.dp), ambientColor = Color.Magenta.copy(alpha = 0.4f))
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(DarkCard)
|
||||
@ -396,7 +403,7 @@ fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.cu
|
||||
}
|
||||
CardTheme.NEON -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(4.dp, RoundedCornerShape(8.dp), ambientColor = Color.Cyan)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(Color(0xFF0A0A0A))
|
||||
@ -406,7 +413,7 @@ fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.cu
|
||||
}
|
||||
CardTheme.PASTEL -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(2.dp, RoundedCornerShape(16.dp))
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(Brush.verticalGradient(listOf(Color(0xFFFFF3E0), Color(0xFFFCE4EC))))
|
||||
@ -416,7 +423,7 @@ fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.cu
|
||||
}
|
||||
CardTheme.FOREST -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(2.dp, RoundedCornerShape(6.dp))
|
||||
.clip(RoundedCornerShape(6.dp))
|
||||
.background(Brush.verticalGradient(listOf(Color(0xFF2E7D32), Color(0xFF1B5E20))))
|
||||
@ -426,7 +433,7 @@ fun CardBack(modifier: Modifier = Modifier, theme: CardTheme = LocalCardTheme.cu
|
||||
}
|
||||
CardTheme.OCEAN -> {
|
||||
Box(
|
||||
modifier = modifier.width(60.dp).height(90.dp)
|
||||
modifier = modifier.width(w).height(h)
|
||||
.shadow(3.dp, RoundedCornerShape(10.dp))
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(Brush.verticalGradient(listOf(Color(0xFF0277BD), Color(0xFF00BCD4))))
|
||||
|
||||
@ -14,6 +14,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.unogame.model.Card
|
||||
import com.unogame.model.CardColor
|
||||
import com.unogame.ui.theme.LocalCardScale
|
||||
|
||||
@Composable
|
||||
fun PlayerHand(
|
||||
@ -25,6 +26,7 @@ fun PlayerHand(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
val cardScale = LocalCardScale.current
|
||||
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
@ -45,6 +47,7 @@ fun PlayerHand(
|
||||
card = card,
|
||||
selected = index == selectedIndex,
|
||||
playable = isPlayable,
|
||||
scale = cardScale,
|
||||
onClick = { onCardClick(index) },
|
||||
modifier = Modifier.padding(horizontal = 2.dp)
|
||||
)
|
||||
|
||||
@ -37,6 +37,7 @@ fun GameScreen(
|
||||
onShowLog: () -> Unit = {},
|
||||
onPlaySeven: (Int) -> Unit = {},
|
||||
isSevenZeroMode: Boolean = false,
|
||||
handOffset: Float = 0f,
|
||||
errorMessage: String
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
@ -44,6 +45,8 @@ fun GameScreen(
|
||||
var showColorPicker by remember { mutableStateOf(false) }
|
||||
var selectedAutoCard by remember { mutableIntStateOf(-1) }
|
||||
val flipped = gameState.flipped
|
||||
val cardScale = LocalCardScale.current
|
||||
val centerScale = 1.8f // 弃牌堆/摸牌堆较大的尺寸
|
||||
|
||||
val topCard = gameState.topCard
|
||||
val currentPlayer = gameState.currentPlayer
|
||||
@ -63,7 +66,7 @@ fun GameScreen(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState)
|
||||
.padding(top = 24.dp, bottom = 100.dp)
|
||||
.padding(top = 16.dp, bottom = (100f - handOffset).coerceAtLeast(0f).dp)
|
||||
) {
|
||||
// 出牌状态条,最多2行
|
||||
Box(modifier = Modifier.fillMaxWidth().heightIn(min = 36.dp, max = 56.dp)) {
|
||||
@ -144,7 +147,7 @@ fun GameScreen(
|
||||
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
}
|
||||
|
||||
// Other players
|
||||
@ -176,7 +179,7 @@ fun GameScreen(
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
|
||||
// Center area: discard pile + draw pile
|
||||
Row(
|
||||
@ -189,6 +192,7 @@ fun GameScreen(
|
||||
// Draw pile
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
CardBack(
|
||||
scale = centerScale,
|
||||
modifier = Modifier.clickable(enabled = isMyTurn) {
|
||||
onDrawCard()
|
||||
}
|
||||
@ -216,6 +220,7 @@ fun GameScreen(
|
||||
color = if (gameState.currentWildColor != null && topCard.color == CardColor.WILD)
|
||||
gameState.currentWildColor!! else displayTop.color
|
||||
),
|
||||
scale = centerScale,
|
||||
playable = false
|
||||
)
|
||||
}
|
||||
@ -325,6 +330,7 @@ fun GameScreen(
|
||||
},
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.offset(y = (-handOffset).dp)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||
.background(LocalTableBg.current.color.copy(alpha = 0.9f))
|
||||
|
||||
@ -121,6 +121,7 @@ fun LocalGameScreen(
|
||||
humanPlayerName: String,
|
||||
mode: GameMode,
|
||||
botNames: List<String> = emptyList(),
|
||||
handOffset: Float = 0f,
|
||||
onBackToMenu: () -> Unit
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
@ -600,6 +601,7 @@ fun LocalGameScreen(
|
||||
myPlayerId = myPlayerId,
|
||||
isMyTurn = isMyTurn,
|
||||
errorMessage = errorMessage,
|
||||
handOffset = handOffset,
|
||||
isSevenZeroMode = mode == GameMode.SEVEN_ZERO,
|
||||
onPlayCard = { index -> executePlay(index, selectedWildColor) },
|
||||
onPlaySeven = { index -> executePlay(index, null) },
|
||||
|
||||
@ -41,9 +41,11 @@ fun SettingsScreen(
|
||||
currentTheme: CardTheme,
|
||||
currentBg: TableBg,
|
||||
isLandscape: Boolean,
|
||||
handOffset: Float,
|
||||
onNameChanged: (String) -> Unit,
|
||||
onSetTheme: (CardTheme) -> Unit,
|
||||
onSetBg: (TableBg) -> Unit,
|
||||
onSetHandOffset: (Float) -> Unit,
|
||||
onToggleOrientation: () -> Unit,
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
@ -237,6 +239,37 @@ fun SettingsScreen(
|
||||
onClick = onToggleOrientation
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
// 手牌区高度调整
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = DarkSurface)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.UnfoldLess, null, tint = Color.White.copy(alpha = 0.6f), modifier = Modifier.size(20.dp))
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text("手牌区高度", color = Color.White, fontSize = 15.sp, modifier = Modifier.weight(1f))
|
||||
Text("${handOffset.toInt()}dp", color = GoldAccent, fontSize = 14.sp)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Slider(
|
||||
value = handOffset,
|
||||
onValueChange = { onSetHandOffset(it) },
|
||||
valueRange = 0f..240f,
|
||||
steps = 23,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = SliderDefaults.colors(
|
||||
thumbColor = GoldAccent,
|
||||
activeTrackColor = GoldAccent
|
||||
)
|
||||
)
|
||||
Text("贴底 ← → 抬高", color = Color.White.copy(alpha = 0.35f), fontSize = 11.sp)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(28.dp))
|
||||
|
||||
// About
|
||||
|
||||
@ -1,6 +1,30 @@
|
||||
package com.unogame.ui.theme
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
|
||||
val LocalCardTheme = compositionLocalOf { CardTheme.ELEGANT }
|
||||
val LocalTableBg = compositionLocalOf { TableBg.GREEN }
|
||||
val LocalCardScale = compositionLocalOf { 1.0f }
|
||||
|
||||
// 手牌缩放:0.5 ~ 1.3,默认 1.0(原始大小)
|
||||
fun loadCardScale(context: Context): Float {
|
||||
return context.getSharedPreferences("unogame_prefs", Context.MODE_PRIVATE)
|
||||
.getFloat("card_scale", 1.0f)
|
||||
}
|
||||
|
||||
fun saveCardScale(context: Context, scale: Float) {
|
||||
context.getSharedPreferences("unogame_prefs", Context.MODE_PRIVATE)
|
||||
.edit().putFloat("card_scale", scale).apply()
|
||||
}
|
||||
|
||||
// 手牌区高度偏移(dp),越大手牌越靠上。默认 160,范围 0~240
|
||||
fun loadHandOffset(context: Context): Float {
|
||||
return context.getSharedPreferences("unogame_prefs", Context.MODE_PRIVATE)
|
||||
.getFloat("hand_offset", 160f)
|
||||
}
|
||||
|
||||
fun saveHandOffset(context: Context, offset: Float) {
|
||||
context.getSharedPreferences("unogame_prefs", Context.MODE_PRIVATE)
|
||||
.edit().putFloat("hand_offset", offset).apply()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user