mirror of
http://180.163.74.83:13000/zhangzhenghao/MPVN_Android.git
synced 2025-12-13 07:34:31 +00:00
增加天气动画
This commit is contained in:
parent
0b4fbe3be2
commit
2c5afcfd6c
@ -3,71 +3,46 @@ package com.example.smarthome.ui
|
|||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.PressInteraction
|
import androidx.compose.foundation.interaction.PressInteraction
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.animation.core.*
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.draw.scale
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Shadow
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import com.example.smarthome.R
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import com.example.smarthome.R
|
||||||
|
import com.example.smarthome.data.WeatherInfo
|
||||||
|
import com.example.smarthome.data.WeatherService
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import android.view.SoundEffectConstants
|
import android.view.SoundEffectConstants
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.foundation.layout.offset
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
|
||||||
import androidx.compose.animation.core.animateFloat
|
|
||||||
import androidx.compose.animation.core.infiniteRepeatable
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.animation.core.LinearEasing
|
|
||||||
import androidx.compose.animation.core.RepeatMode
|
|
||||||
import com.example.smarthome.data.WeatherService
|
|
||||||
import com.example.smarthome.data.WeatherInfo
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainScaffold(
|
fun MainScaffold(
|
||||||
@ -580,12 +555,13 @@ fun NavRailItem(text: String, iconRes: Int, selected: Boolean, onClick: () -> Un
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TopBar() {
|
fun TopBar() {
|
||||||
|
val context = androidx.compose.ui.platform.LocalContext.current
|
||||||
var weatherInfo by remember { mutableStateOf(WeatherService.getSimulatedWeather()) }
|
var weatherInfo by remember { mutableStateOf(WeatherService.getSimulatedWeather()) }
|
||||||
var isLoading by remember { mutableStateOf(true) }
|
var isLoading by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
try {
|
try {
|
||||||
weatherInfo = WeatherService.getWeather()
|
weatherInfo = WeatherService.getWeather(context)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// 使用模拟数据
|
// 使用模拟数据
|
||||||
}
|
}
|
||||||
@ -604,28 +580,106 @@ fun TopBar() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun WeatherCard(weatherInfo: WeatherInfo, isLoading: Boolean) {
|
fun WeatherCard(weatherInfo: WeatherInfo, isLoading: Boolean) {
|
||||||
|
// 动画:创建无限循环的偏移量
|
||||||
|
val infiniteTransition = rememberInfiniteTransition(label = "weather")
|
||||||
|
val offsetAnim by infiniteTransition.animateFloat(
|
||||||
|
initialValue = 0f,
|
||||||
|
targetValue = 1500f, // 增加偏移量,让流动范围更大
|
||||||
|
animationSpec = infiniteRepeatable(
|
||||||
|
animation = tween(durationMillis = 15000, easing = LinearEasing), // 加快一点速度
|
||||||
|
repeatMode = RepeatMode.Reverse
|
||||||
|
),
|
||||||
|
label = "gradient"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 根据天气状况决定背景颜色 - 增加颜色差异让流动更明显
|
||||||
|
val colors = if (isLoading) {
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2C3E50).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF3498DB).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF2C3E50).copy(alpha = 0.6f)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
when {
|
||||||
|
// 晴天:暗橙色流动
|
||||||
|
weatherInfo.weather.contains("晴") ->
|
||||||
|
listOf(
|
||||||
|
Color(0xFFB8450A).copy(alpha = 0.55f),
|
||||||
|
Color(0xFFC06000).copy(alpha = 0.55f),
|
||||||
|
Color(0xFFB8450A).copy(alpha = 0.55f)
|
||||||
|
)
|
||||||
|
// 雨天:深紫深蓝流动
|
||||||
|
weatherInfo.weather.contains("雨") ->
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2C3E50).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF4CA1AF).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF2C3E50).copy(alpha = 0.6f)
|
||||||
|
)
|
||||||
|
// 阴天/多云:灰蓝流动
|
||||||
|
weatherInfo.weather.contains("云") || weatherInfo.weather.contains("阴") ->
|
||||||
|
listOf(
|
||||||
|
Color(0xFF606c88).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF3f4c6b).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF606c88).copy(alpha = 0.6f)
|
||||||
|
)
|
||||||
|
// 雪天:冰蓝流动
|
||||||
|
weatherInfo.weather.contains("雪") ->
|
||||||
|
listOf(
|
||||||
|
Color(0xFF5a7fa4).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF8ad0d4).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF5a7fa4).copy(alpha = 0.6f)
|
||||||
|
)
|
||||||
|
// 默认:蓝青流动
|
||||||
|
else ->
|
||||||
|
listOf(
|
||||||
|
Color(0xFF1090B0).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF000046).copy(alpha = 0.6f),
|
||||||
|
Color(0xFF1090B0).copy(alpha = 0.6f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val backgroundBrush = Brush.linearGradient(
|
||||||
|
colors = colors,
|
||||||
|
start = Offset(offsetAnim, offsetAnim),
|
||||||
|
end = Offset(offsetAnim + 500f, offsetAnim + 500f)
|
||||||
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(16.dp))
|
.clip(RoundedCornerShape(16.dp))
|
||||||
.background(Color(0x50121212))
|
.background(backgroundBrush) // 使用动态渐变背景
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
||||||
) {
|
) {
|
||||||
|
// 天气特效层(在背景之上,内容之下)- 使用固定大小
|
||||||
|
WeatherEffectLayer(
|
||||||
|
weather = weatherInfo.weather,
|
||||||
|
modifier = Modifier.size(width = 300.dp, height = 60.dp)
|
||||||
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
modifier = Modifier.padding(horizontal = 20.dp, vertical = 12.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(20.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
// 温度和天气
|
// 温度和天气
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Text(
|
Text(
|
||||||
text = if (isLoading) "--" else "${weatherInfo.temperature}°C",
|
text = if (isLoading) "--" else "${weatherInfo.temperature}°C",
|
||||||
fontSize = 18.sp,
|
fontSize = 22.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = Color.White
|
color = Color.White,
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = if (isLoading) "加载中" else weatherInfo.weather,
|
text = if (isLoading) "加载中" else weatherInfo.weather,
|
||||||
fontSize = 12.sp,
|
fontSize = 14.sp,
|
||||||
color = Color(0xFF9AA0A6)
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color.White,
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,22 +687,28 @@ fun WeatherCard(weatherInfo: WeatherInfo, isLoading: Boolean) {
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(1.dp)
|
.width(1.dp)
|
||||||
.height(30.dp)
|
.height(36.dp)
|
||||||
.background(Color(0x33FFFFFF))
|
.background(Color.White.copy(alpha = 0.3f))
|
||||||
)
|
)
|
||||||
|
|
||||||
// 湿度
|
// 湿度
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Text(
|
Text(
|
||||||
text = if (isLoading) "--" else "${weatherInfo.humidity}%",
|
text = if (isLoading) "--" else "${weatherInfo.humidity}%",
|
||||||
fontSize = 14.sp,
|
fontSize = 18.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.SemiBold,
|
||||||
color = Color.White
|
color = Color.White,
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "湿度",
|
text = "湿度",
|
||||||
fontSize = 11.sp,
|
fontSize = 13.sp,
|
||||||
color = Color(0xFF9AA0A6)
|
color = Color.White.copy(alpha = 0.8f),
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,36 +716,46 @@ fun WeatherCard(weatherInfo: WeatherInfo, isLoading: Boolean) {
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(1.dp)
|
.width(1.dp)
|
||||||
.height(30.dp)
|
.height(36.dp)
|
||||||
.background(Color(0x33FFFFFF))
|
.background(Color.White.copy(alpha = 0.3f))
|
||||||
)
|
)
|
||||||
|
|
||||||
// 空气质量
|
// 空气质量
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
val aqiColor = when {
|
val aqiColor = when {
|
||||||
weatherInfo.aqi <= 50 -> Color(0xFF00E676)
|
weatherInfo.aqi <= 50 -> Color(0xFF4CAF50)
|
||||||
weatherInfo.aqi <= 100 -> Color(0xFFFFEB3B)
|
weatherInfo.aqi <= 100 -> Color(0xFFFFEB3B)
|
||||||
weatherInfo.aqi <= 150 -> Color(0xFFFF9800)
|
weatherInfo.aqi <= 150 -> Color(0xFFFF9800)
|
||||||
else -> Color(0xFFFF5252)
|
else -> Color(0xFFFF5252)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = if (isLoading) "--" else weatherInfo.airQuality,
|
text = if (isLoading) "--" else weatherInfo.airQuality,
|
||||||
fontSize = 14.sp,
|
fontSize = 18.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.SemiBold,
|
||||||
color = aqiColor
|
color = aqiColor,
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = if (isLoading) "AQI" else "AQI ${weatherInfo.aqi}",
|
text = if (isLoading) "AQI" else "AQI ${weatherInfo.aqi}",
|
||||||
fontSize = 11.sp,
|
fontSize = 13.sp,
|
||||||
color = Color(0xFF9AA0A6)
|
color = Color.White.copy(alpha = 0.8f),
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 城市
|
// 城市
|
||||||
Text(
|
Text(
|
||||||
text = weatherInfo.city,
|
text = weatherInfo.city,
|
||||||
fontSize = 12.sp,
|
fontSize = 15.sp,
|
||||||
color = Color(0xFFB0B0B0)
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color.White,
|
||||||
|
style = androidx.compose.ui.text.TextStyle(
|
||||||
|
shadow = Shadow(color = Color.Black.copy(alpha = 0.3f), blurRadius = 4f)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1544,6 +1614,130 @@ fun LightCard(name: String, percent: Float, modifier: Modifier = Modifier) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WeatherEffectLayer(weather: String, modifier: Modifier = Modifier) {
|
||||||
|
val infiniteTransition = rememberInfiniteTransition(label = "weather_effect")
|
||||||
|
|
||||||
|
// 太阳旋转动画
|
||||||
|
val sunRotation by infiniteTransition.animateFloat(
|
||||||
|
initialValue = 0f,
|
||||||
|
targetValue = 360f,
|
||||||
|
animationSpec = infiniteRepeatable(
|
||||||
|
animation = tween(20000, easing = LinearEasing)
|
||||||
|
),
|
||||||
|
label = "sun_rotation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 雨雪下落动画
|
||||||
|
val dropOffset by infiniteTransition.animateFloat(
|
||||||
|
initialValue = 0f,
|
||||||
|
targetValue = 1f,
|
||||||
|
animationSpec = infiniteRepeatable(
|
||||||
|
animation = tween(1500, easing = LinearEasing)
|
||||||
|
),
|
||||||
|
label = "drop_offset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 云朵飘动动画
|
||||||
|
val cloudOffset by infiniteTransition.animateFloat(
|
||||||
|
initialValue = -20f,
|
||||||
|
targetValue = 20f,
|
||||||
|
animationSpec = infiniteRepeatable(
|
||||||
|
animation = tween(5000, easing = LinearEasing),
|
||||||
|
repeatMode = RepeatMode.Reverse
|
||||||
|
),
|
||||||
|
label = "cloud_offset"
|
||||||
|
)
|
||||||
|
|
||||||
|
androidx.compose.foundation.Canvas(modifier = modifier) {
|
||||||
|
val width = size.width
|
||||||
|
val height = size.height
|
||||||
|
|
||||||
|
when {
|
||||||
|
// 晴天:绘制旋转的太阳
|
||||||
|
weather.contains("晴") -> {
|
||||||
|
// 太阳核心
|
||||||
|
val sunCenterX = width - 25.dp.toPx()
|
||||||
|
val sunCenterY = 25.dp.toPx()
|
||||||
|
|
||||||
|
drawCircle(
|
||||||
|
color = Color(0xFFFFD700).copy(alpha = 0.6f),
|
||||||
|
radius = 18.dp.toPx(),
|
||||||
|
center = Offset(sunCenterX, sunCenterY)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 太阳光芒 - 使用数学计算位置
|
||||||
|
val rayLength = 10.dp.toPx()
|
||||||
|
val rayStart = 20.dp.toPx()
|
||||||
|
|
||||||
|
for (i in 0 until 8) {
|
||||||
|
val angle = Math.toRadians((sunRotation + i * 45f).toDouble())
|
||||||
|
val startX = sunCenterX + kotlin.math.cos(angle).toFloat() * rayStart
|
||||||
|
val startY = sunCenterY + kotlin.math.sin(angle).toFloat() * rayStart
|
||||||
|
val endX = sunCenterX + kotlin.math.cos(angle).toFloat() * (rayStart + rayLength)
|
||||||
|
val endY = sunCenterY + kotlin.math.sin(angle).toFloat() * (rayStart + rayLength)
|
||||||
|
|
||||||
|
drawLine(
|
||||||
|
color = Color(0xFFFFD700).copy(alpha = 0.5f),
|
||||||
|
start = Offset(startX, startY),
|
||||||
|
end = Offset(endX, endY),
|
||||||
|
strokeWidth = 2.dp.toPx()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 雨天:绘制下落的雨滴
|
||||||
|
weather.contains("雨") -> {
|
||||||
|
val dropCount = 8
|
||||||
|
val dropLength = 8.dp.toPx()
|
||||||
|
|
||||||
|
for (i in 0 until dropCount) {
|
||||||
|
val x = (i * width / dropCount) + (i * 17 % 30)
|
||||||
|
val startY = (i * 29 % height.toInt()).toFloat()
|
||||||
|
val currentY = (startY + dropOffset * height) % height
|
||||||
|
|
||||||
|
drawLine(
|
||||||
|
color = Color.White.copy(alpha = 0.3f),
|
||||||
|
start = Offset(x, currentY),
|
||||||
|
end = Offset(x - 2.dp.toPx(), currentY + dropLength),
|
||||||
|
strokeWidth = 1.5f.dp.toPx()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 雪天:绘制飘落的雪花(圆点)
|
||||||
|
weather.contains("雪") -> {
|
||||||
|
val snowCount = 8
|
||||||
|
|
||||||
|
for (i in 0 until snowCount) {
|
||||||
|
val x = (i * width / snowCount) + (i * 23 % 40)
|
||||||
|
val startY = (i * 41 % height.toInt()).toFloat()
|
||||||
|
val currentY = (startY + dropOffset * height * 0.5f) % height
|
||||||
|
|
||||||
|
drawCircle(
|
||||||
|
color = Color.White.copy(alpha = 0.5f),
|
||||||
|
radius = (1.5f + i % 2).dp.toPx(),
|
||||||
|
center = Offset(x, currentY)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多云/阴天:绘制云朵
|
||||||
|
weather.contains("云") || weather.contains("阴") -> {
|
||||||
|
// 绘制几个叠加的圆组成云 - 缩小尺寸
|
||||||
|
val cloudColor = Color.White.copy(alpha = 0.15f)
|
||||||
|
val baseX = width - 35.dp.toPx() + cloudOffset * 0.5f
|
||||||
|
val baseY = 25.dp.toPx()
|
||||||
|
|
||||||
|
drawCircle(color = cloudColor, radius = 15.dp.toPx(), center = Offset(baseX, baseY))
|
||||||
|
drawCircle(color = cloudColor, radius = 12.dp.toPx(), center = Offset(baseX - 18.dp.toPx(), baseY + 5.dp.toPx()))
|
||||||
|
drawCircle(color = cloudColor, radius = 14.dp.toPx(), center = Offset(baseX + 15.dp.toPx(), baseY + 3.dp.toPx()))
|
||||||
|
drawCircle(color = cloudColor, radius = 10.dp.toPx(), center = Offset(baseX - 8.dp.toPx(), baseY - 8.dp.toPx()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AddRoomDialog(
|
fun AddRoomDialog(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user