优化细节

This commit is contained in:
zzh 2025-11-27 16:00:44 +08:00
parent a9f61e0663
commit ae9723964e
8 changed files with 328 additions and 80 deletions

View File

@ -26,6 +26,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.layout.ContentScale
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.collectAsState
import com.example.smarthome.data.BackgroundManager
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -113,10 +115,20 @@ fun AppRoot() {
rooms = roomList
}
// 初始化背景管理器并获取当前选中的背景
androidx.compose.runtime.LaunchedEffect(Unit) {
BackgroundManager.init(context)
}
val selectedBgId by BackgroundManager.selectedBackground.collectAsState()
val currentBg = BackgroundManager.backgrounds.getOrNull(selectedBgId)
val backgroundRes = currentBg?.resourceId ?: R.drawable.background1
// 根据背景类型调整遮罩透明度:暗色背景减少遮罩,亮色背景增加遮罩
val overlayAlpha = if (currentBg?.isDark == true) 0x11 else 0x88
Box(modifier = Modifier.fillMaxSize()) {
// 背景图片 - 填充整个屏幕包括系统栏使用FillBounds确保完全填充
Image(
painter = painterResource(id = R.drawable.background),
painter = painterResource(id = backgroundRes),
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.FillBounds,
@ -127,7 +139,7 @@ fun AppRoot() {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0x88121212))
.background(Color(overlayAlpha shl 24 or 0x121212))
)
// 主内容 - 添加系统栏内边距

View File

@ -26,6 +26,11 @@ data class WeatherInfo(
object WeatherService {
private const val TAG = "WeatherService"
// 缓存天气数据,避免重复获取
private var cachedWeather: WeatherInfo? = null
private var lastFetchTime: Long = 0
private const val CACHE_DURATION = 10 * 60 * 1000L // 10分钟缓存
private val client = OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
@ -34,8 +39,16 @@ object WeatherService {
/**
* 获取天气信息
* 优先使用GPS定位失败则用IP定位
* 带缓存机制10分钟内不重复获取
*/
suspend fun getWeather(context: Context): WeatherInfo {
suspend fun getWeather(context: Context, forceRefresh: Boolean = false): WeatherInfo {
// 检查缓存
val now = System.currentTimeMillis()
if (!forceRefresh && cachedWeather != null && (now - lastFetchTime) < CACHE_DURATION) {
Log.d(TAG, "Using cached weather data")
return cachedWeather!!
}
return withContext(Dispatchers.IO) {
// 1. 优先尝试GPS定位
val gpsLocation = getGpsLocation(context)
@ -46,6 +59,8 @@ object WeatherService {
// 用GPS坐标获取天气
val weatherResult = getWeatherByLocation(lat, lon, city)
if (weatherResult != null) {
cachedWeather = weatherResult
lastFetchTime = now
return@withContext weatherResult
}
}
@ -54,6 +69,8 @@ object WeatherService {
Log.w(TAG, "GPS failed, trying wttr.in...")
val wttrResult = tryWttrIn()
if (wttrResult != null) {
cachedWeather = wttrResult
lastFetchTime = now
return@withContext wttrResult
}
@ -61,6 +78,8 @@ object WeatherService {
Log.w(TAG, "wttr.in failed, trying backup...")
val backupResult = tryBackupApi()
if (backupResult != null) {
cachedWeather = backupResult
lastFetchTime = now
return@withContext backupResult
}

View File

@ -316,7 +316,7 @@ fun RoomTabs(
}
// 固定的添加按钮
GradientButton("+ 添加", onClick = onAddRoomClick)
GradientButton("+ 添加房间", onClick = onAddRoomClick)
}
}
@ -490,17 +490,82 @@ fun NavItem(title: String, selected: Boolean) {
@Composable
fun SideNavRail(selectedNavItem: Int = 0, onNavItemSelect: (Int) -> Unit = {}) {
Column(modifier = Modifier.width(100.dp).fillMaxHeight().padding(start = 12.dp, end = 4.dp, top = 12.dp, bottom = 12.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
Spacer(modifier = Modifier.height(48.dp))
NavRailItem("控制台", R.drawable.ic_dashboard, selectedNavItem == 0, onClick = { onNavItemSelect(0) })
NavRailItem("场景", R.drawable.ic_scene, selectedNavItem == 1, onClick = { onNavItemSelect(1) })
NavRailItem("自动化", R.drawable.ic_automation, selectedNavItem == 2, onClick = { onNavItemSelect(2) })
NavRailItem("统计", R.drawable.ic_statistics, selectedNavItem == 3, onClick = { onNavItemSelect(3) })
NavRailItem("安全", R.drawable.ic_security, selectedNavItem == 4, onClick = { onNavItemSelect(4) })
NavRailItem("设置", R.drawable.ic_settings, selectedNavItem == 5, onClick = { onNavItemSelect(5) })
val context = androidx.compose.ui.platform.LocalContext.current
val selectedBg by com.example.smarthome.data.BackgroundManager.selectedBackground.collectAsState()
val isDarkMode = com.example.smarthome.data.BackgroundManager.backgrounds.getOrNull(selectedBg)?.isDark ?: false
Column(
modifier = Modifier
.width(100.dp)
.fillMaxHeight()
.padding(start = 12.dp, end = 4.dp, top = 12.dp, bottom = 12.dp),
verticalArrangement = Arrangement.SpaceBetween
) {
// 上半部分:导航项
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
Spacer(modifier = Modifier.height(48.dp))
NavRailItem("控制台", R.drawable.ic_dashboard, selectedNavItem == 0, onClick = { onNavItemSelect(0) })
NavRailItem("场景", R.drawable.ic_scene, selectedNavItem == 1, onClick = { onNavItemSelect(1) })
NavRailItem("自动化", R.drawable.ic_automation, selectedNavItem == 2, onClick = { onNavItemSelect(2) })
NavRailItem("统计", R.drawable.ic_statistics, selectedNavItem == 3, onClick = { onNavItemSelect(3) })
NavRailItem("安全", R.drawable.ic_security, selectedNavItem == 4, onClick = { onNavItemSelect(4) })
NavRailItem("设置", R.drawable.ic_settings, selectedNavItem == 5, onClick = { onNavItemSelect(5) })
}
// 底部:模式切换按钮(暂时注释)
/*
ThemeModeToggle(
isDarkMode = isDarkMode,
onToggle = {
if (isDarkMode) {
com.example.smarthome.data.BackgroundManager.setBackground(context, 0) // 丝绸白
} else {
com.example.smarthome.data.BackgroundManager.setBackground(context, 2) // 紫金绸
}
}
)
*/
}
}
/*
@Composable
fun ThemeModeToggle(isDarkMode: Boolean, onToggle: () -> Unit) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) { onToggle() }
.padding(vertical = 4.dp)
) {
Box(
modifier = Modifier
.size(48.dp)
.clip(RoundedCornerShape(14.dp))
.background(
if (isDarkMode) {
Brush.linearGradient(
listOf(Color(0xFF2C2C54), Color(0xFF1A1A2E))
)
} else {
Brush.linearGradient(
listOf(Color(0xFFFFE082), Color(0xFFFFD54F))
)
}
),
contentAlignment = Alignment.Center
) {
Text(
text = if (isDarkMode) "🌙" else "☀️",
fontSize = 20.sp
)
}
}
}
*/
@Composable
fun NavRailItem(text: String, iconRes: Int, selected: Boolean, onClick: () -> Unit = {}) {
val scale by androidx.compose.animation.core.animateFloatAsState(
@ -574,11 +639,7 @@ fun TopBar() {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
Text(text = "控制台", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, color = Color.White)
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
// 天气信息卡片
WeatherCard(weatherInfo = weatherInfo, isLoading = isLoading)
GradientButton("+ 添加设备")
}
WeatherCard(weatherInfo = weatherInfo, isLoading = isLoading)
}
}
@ -1060,9 +1121,40 @@ fun AirConditionerCard(modifier: Modifier = Modifier, roomName: String = "房间
var selectedMode by remember { mutableStateOf(0) } // 0:制冷 1:制热 2:除湿 3:送风
var fanSpeed by remember { mutableStateOf(1) } // 0:自动 1:低 2:中 3:高
val modes = listOf("❄️" to "制冷", "🔥" to "制热", "💧" to "除湿", "🌀" to "送风")
// 模式emoji图标
val modeIcons = listOf(
"❄️" to "制冷",
"☀️" to "制热",
"💧" to "除湿",
"🌀" to "送风"
)
val fanSpeeds = listOf("自动", "", "", "")
// 图标动画
val infiniteTransition = rememberInfiniteTransition(label = "ac_icon")
// 旋转动画(制冷、制热、送风)
val iconRotation by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 3000, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "icon_rotation"
)
// 水滴下落动画(除湿)
val dropOffset by infiniteTransition.animateFloat(
initialValue = -2f,
targetValue = 2f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 800, easing = androidx.compose.animation.core.EaseInOut),
repeatMode = RepeatMode.Reverse
),
label = "drop_offset"
)
// 根据模式决定主题色
val accentColor = when (selectedMode) {
0 -> Color(0xFF4FC3F7) // 制冷 - 蓝色
@ -1071,6 +1163,9 @@ fun AirConditionerCard(modifier: Modifier = Modifier, roomName: String = "房间
else -> Color(0xFFB0BEC5) // 送风 - 灰色
}
// 当前模式的emoji
val currentEmoji = modeIcons[selectedMode].first
Box(
modifier = modifier
.height(260.dp)
@ -1096,7 +1191,7 @@ fun AirConditionerCard(modifier: Modifier = Modifier, roomName: String = "房间
modifier = Modifier.fillMaxWidth()
) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
// 空调图标
// 空调图标 - 根据模式应用不同动画
Box(
modifier = Modifier
.size(36.dp)
@ -1104,7 +1199,17 @@ fun AirConditionerCard(modifier: Modifier = Modifier, roomName: String = "房间
.background(accentColor.copy(alpha = if (isOn) 0.3f else 0.1f)),
contentAlignment = Alignment.Center
) {
Text(text = "❄️", fontSize = 18.sp)
// 根据模式选择动画:除湿用上下移动,其他用旋转
val emojiModifier = when {
!isOn -> Modifier
selectedMode == 2 -> Modifier.offset(y = dropOffset.dp) // 除湿:上下移动
else -> Modifier.rotate(iconRotation) // 其他:旋转
}
Text(
text = currentEmoji,
fontSize = 18.sp,
modifier = emojiModifier
)
}
Column {
Text(text = "空调", fontWeight = FontWeight.SemiBold, color = Color.White, fontSize = 16.sp)
@ -1177,22 +1282,28 @@ fun AirConditionerCard(modifier: Modifier = Modifier, roomName: String = "房间
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
modes.forEachIndexed { index, (icon, name) ->
modeIcons.forEachIndexed { index, (emoji, name) ->
val isSelected = selectedMode == index
val modeColor = when (index) {
0 -> Color(0xFF4FC3F7)
1 -> Color(0xFFFF8A65)
2 -> Color(0xFF81C784)
else -> Color(0xFFB0BEC5)
}
Box(
modifier = Modifier
.weight(1f)
.height(44.dp)
.clip(RoundedCornerShape(12.dp))
.background(
if (isSelected && isOn) accentColor.copy(alpha = 0.4f)
if (isSelected && isOn) modeColor.copy(alpha = 0.4f)
else Color(0xFF2A2A3E).copy(alpha = 0.6f)
)
.clickable(enabled = isOn) { selectedMode = index },
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = icon, fontSize = 14.sp)
Text(text = emoji, fontSize = 14.sp)
Text(
text = name,
fontSize = 10.sp,

View File

@ -1,5 +1,6 @@
package com.example.smarthome.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
@ -15,9 +16,13 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.smarthome.data.BackgroundManager
@Composable
fun SettingsScreen(onBack: () -> Unit) {
@ -75,12 +80,25 @@ fun SettingsContentList() {
}}
item { SettingsSection(title = "显示设置") {
var darkMode by remember { mutableStateOf(true) }
BackgroundSelector()
val context = LocalContext.current
val selectedBg by BackgroundManager.selectedBackground.collectAsState()
// 深色模式根据当前背景是否为暗色来判断
val isDarkMode = BackgroundManager.backgrounds.getOrNull(selectedBg)?.isDark ?: false
SettingsSwitchItem(
title = "深色模式",
subtitle = "使用深色主题",
checked = darkMode,
onCheckedChange = { darkMode = it }
checked = isDarkMode,
onCheckedChange = { dark ->
// 切换深色/浅色模式时自动更换背景
if (dark) {
BackgroundManager.setBackground(context, 2) // 紫金绸
} else {
BackgroundManager.setBackground(context, 0) // 丝绸白
}
}
)
SettingsItem(
@ -355,3 +373,117 @@ fun SettingsContent() {
SettingsContentList()
}
}
@Composable
fun BackgroundSelector() {
val context = LocalContext.current
val selectedBackground by BackgroundManager.selectedBackground.collectAsState()
val interactionSources = remember {
BackgroundManager.backgrounds.map { MutableInteractionSource() }
}
Column(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(Color(0x33121212))
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
text = "背景壁纸",
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
Text(
text = "选择您喜欢的背景图片",
fontSize = 13.sp,
color = Color(0xFF9AA0A6)
)
Spacer(modifier = Modifier.height(4.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
BackgroundManager.backgrounds.forEachIndexed { index, bg ->
val isSelected = selectedBackground == bg.id
Column(
modifier = Modifier.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.clip(RoundedCornerShape(10.dp))
.then(
if (isSelected) {
Modifier.border(
width = 2.dp,
brush = Brush.linearGradient(
listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))
),
shape = RoundedCornerShape(10.dp)
)
} else Modifier
)
.clickable(
indication = null,
interactionSource = interactionSources[index]
) {
BackgroundManager.setBackground(context, bg.id)
}
) {
Image(
painter = painterResource(id = bg.thumbId),
contentDescription = bg.name,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
if (isSelected) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 0.3f)),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(20.dp)
.clip(RoundedCornerShape(10.dp))
.background(
Brush.linearGradient(
listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))
)
),
contentAlignment = Alignment.Center
) {
Text(
text = "",
color = Color.White,
fontSize = 12.sp,
fontWeight = FontWeight.Bold
)
}
}
}
}
Text(
text = bg.name,
fontSize = 11.sp,
fontWeight = if (isSelected) FontWeight.Medium else FontWeight.Normal,
color = if (isSelected) Color(0xFFA9F0FF) else Color(0xFF9AA0A6)
)
}
}
}
}
}

View File

@ -4,28 +4,8 @@
android:viewportWidth="24"
android:viewportHeight="24">
<!-- 自动化图标 - 齿轮和箭头 -->
<!-- 自动化图标 - 闪电 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,2 L10.5,4.5 L7.5,4.5 L6,7 L3.5,8.5 L3.5,11.5 L6,13 L7.5,15.5 L10.5,15.5 L12,18 L13.5,15.5 L16.5,15.5 L18,13 L20.5,11.5 L20.5,8.5 L18,7 L16.5,4.5 L13.5,4.5 Z M12,8 C14.21,8 16,9.79 16,12 C16,14.21 14.21,16 12,16 C9.79,16 8,14.21 8,12 C8,9.79 9.79,8 12,8 Z"/>
<!-- 内圈 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,10 C10.9,10 10,10.9 10,12 C10,13.1 10.9,14 12,14 C13.1,14 14,13.1 14,12 C14,10.9 13.1,10 12,10 Z"/>
<!-- 循环箭头 -->
<path
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.5"
android:strokeLineCap="round"
android:fillColor="#00000000"
android:pathData="M19,12 C19,15.87 15.87,19 12,19 C8.13,19 5,15.87 5,12 M5,12 L7,10 M5,12 L7,14"/>
<path
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.5"
android:strokeLineCap="round"
android:fillColor="#00000000"
android:pathData="M5,12 C5,8.13 8.13,5 12,5 C15.87,5 19,8.13 19,12 M19,12 L17,10 M19,12 L17,14"/>
android:pathData="M13,2 L4,14 L11,14 L11,22 L20,10 L13,10 L13,2 Z"/>
</vector>

View File

@ -4,28 +4,24 @@
android:viewportWidth="24"
android:viewportHeight="24">
<!-- 场景图标 - 魔法棒 -->
<!-- 场景图标 - 四个方块组成的网格 -->
<!-- 左上 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M20,8 L18,8 L18,6 C18,5.45 17.55,5 17,5 C16.45,5 16,5.45 16,6 L16,8 L14,8 C13.45,8 13,8.45 13,9 C13,9.55 13.45,10 14,10 L16,10 L16,12 C16,12.55 16.45,13 17,13 C17.55,13 18,12.55 18,12 L18,10 L20,10 C20.55,10 21,9.55 21,9 C21,8.45 20.55,8 20,8 Z"/>
android:pathData="M4,4 L10,4 C10.55,4 11,4.45 11,5 L11,10 C11,10.55 10.55,11 10,11 L4,11 C3.45,11 3,10.55 3,10 L3,5 C3,4.45 3.45,4 4,4 Z"/>
<!-- 右上 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M11,4 L10,4 L10,3 C10,2.45 9.55,2 9,2 C8.45,2 8,2.45 8,3 L8,4 L7,4 C6.45,4 6,4.45 6,5 C6,5.55 6.45,6 7,6 L8,6 L8,7 C8,7.55 8.45,8 9,8 C9.55,8 10,7.55 10,7 L10,6 L11,6 C11.55,6 12,5.55 12,5 C12,4.45 11.55,4 11,4 Z"/>
android:pathData="M14,4 L20,4 C20.55,4 21,4.45 21,5 L21,10 C21,10.55 20.55,11 20,11 L14,11 C13.45,11 13,10.55 13,10 L13,5 C13,4.45 13.45,4 14,4 Z"/>
<!-- 左下 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3.5,11 L3.5,10 L2.5,10 C2.22,10 2,9.78 2,9.5 C2,9.22 2.22,9 2.5,9 L3.5,9 L3.5,8 C3.5,7.72 3.72,7.5 4,7.5 C4.28,7.5 4.5,7.72 4.5,8 L4.5,9 L5.5,9 C5.78,9 6,9.22 6,9.5 C6,9.78 5.78,10 5.5,10 L4.5,10 L4.5,11 C4.5,11.28 4.28,11.5 4,11.5 C3.72,11.5 3.5,11.28 3.5,11 Z"/>
android:pathData="M4,13 L10,13 C10.55,13 11,13.45 11,14 L11,19 C11,19.55 10.55,20 10,20 L4,20 C3.45,20 3,19.55 3,19 L3,14 C3,13.45 3.45,13 4,13 Z"/>
<!-- 魔法棒主体 -->
<!-- 右下 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M15.5,14.5 L4.5,3.5 C4.11,3.11 3.48,3.11 3.09,3.5 L3.5,3.91 L14.5,14.91 L15.5,14.5 Z"/>
<path
android:strokeColor="#FFFFFFFF"
android:strokeWidth="2"
android:strokeLineCap="round"
android:fillColor="#00000000"
android:pathData="M15,15 L4,4"/>
android:pathData="M14,13 L20,13 C20.55,13 21,13.45 21,14 L21,19 C21,19.55 20.55,20 20,20 L14,20 C13.45,20 13,19.55 13,19 L13,14 C13,13.45 13.45,13 14,13 Z"/>
</vector>

View File

@ -1,3 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:strokeColor="#FFFFFFFF" android:strokeWidth="2" android:fillColor="#00000000" android:pathData="M12,3 L21,8 L12,21 L3,8 Z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<!-- 安全图标 - 盾牌 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,1 L3,5 L3,11 C3,16.55 6.84,21.74 12,23 C17.16,21.74 21,16.55 21,11 L21,5 L12,1 Z M12,11.99 L19,11.99 C18.47,16.11 15.72,19.78 12,20.93 L12,12 L5,12 L5,6.3 L12,3.19 L12,11.99 Z"/>
</vector>

View File

@ -4,29 +4,19 @@
android:viewportWidth="24"
android:viewportHeight="24">
<!-- 统计图标 - 柱状图 -->
<!-- 统计图标 - 饼图 -->
<!-- 圆环 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M5,19 L5,9 C5,8.45 5.45,8 6,8 L8,8 C8.55,8 9,8.45 9,9 L9,19 C9,19.55 8.55,20 8,20 L6,20 C5.45,20 5,19.55 5,19 Z"/>
android:pathData="M12,2 C6.48,2 2,6.48 2,12 C2,17.52 6.48,22 12,22 C17.52,22 22,17.52 22,12 C22,6.48 17.52,2 12,2 Z M12,20 C7.59,20 4,16.41 4,12 C4,7.59 7.59,4 12,4 C16.41,4 20,7.59 20,12 C20,16.41 16.41,20 12,20 Z"/>
<!-- 扇形部分 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M10,19 L10,5 C10,4.45 10.45,4 11,4 L13,4 C13.55,4 14,4.45 14,5 L14,19 C14,19.55 13.55,20 13,20 L11,20 C10.45,20 10,19.55 10,19 Z"/>
android:pathData="M12,12 L12,4 C16.41,4 20,7.59 20,12 L12,12 Z"/>
<!-- 小扇形 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M15,19 L15,12 C15,11.45 15.45,11 16,11 L18,11 C18.55,11 19,11.45 19,12 L19,19 C19,19.55 18.55,20 18,20 L16,20 C15.45,20 15,19.55 15,19 Z"/>
<!-- 趋势线 -->
<path
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.5"
android:strokeLineCap="round"
android:fillColor="#00000000"
android:pathData="M3,17 L7,13 L12,15 L17,9 L21,11"/>
<!-- 箭头 -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M21,11 L19,9 L19,13 Z"/>
android:pathData="M12,12 L20,12 C20,14.5 19,16.8 17.3,18.3 L12,12 Z"/>
</vector>