diff --git a/AGENTS.md b/AGENTS.md index 71ddc60..a825616 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -133,12 +133,14 @@ val y = power / 100.0 * sin(angle) // 水平分量 ## 构建与运行 -```bash -# 在项目根目录 -./gradlew assembleDebug +> **注意**:项目源码位于 Windows 目录下,通过 WSL 访问和编辑。WSL 环境中没有 Android SDK / Gradle,无法直接运行构建命令。如需构建或安装,请在 Windows 端的 Android Studio 或终端中执行。 -# 安装到设备 -./gradlew installDebug +```bash +# 在项目根目录(Windows 端) +gradlew assembleDebug + +# 安装到设备(Windows 端) +gradlew installDebug ``` ### 依赖 @@ -194,9 +196,12 @@ val y = power / 100.0 * sin(angle) // 水平分量 - [x] UI 布局:增加 bg1.png 作为底图,无视频流时显示(视频流播放时覆盖底图) - [x] UI 布局:开关灯合并为前灯/后灯两个按键,通过颜色(琥珀色=开/暗色=关)表示置位状态,配合机器人回报状态同步 - [x] 状态栏:ICMP 延迟测量 + WiFi 信号强度图标显示,放置于连接状态文字右侧,延迟独立于连接生命周期 +- [x] UI 布局:StatusBar 背景延伸到屏幕顶端,视觉吸附优化(Box + Row 双层结构,背景填满状态栏区域) +- [x] UI 布局:连接按钮合并到顶部 StatusBar 的 ConnectionIndicator,删除底部独立连接按钮 +- [x] UI 布局:ConnectionIndicator 改为按钮形态(Surface + 圆角边框),仅指示器区域可点击切换连接 +- [x] UI 布局:隐藏系统状态栏(WindowInsetsControllerCompat),压缩自定义 StatusBar 高度,扩展可视区域 ### 待办 -- [ ] UI 布局:header 部分虽已避开状态栏,但底色与屏幕顶端视觉不吸附,需优化视觉传达效果 - [ ] UI 布局:功能按钮均布在四周,充分利用屏幕空间,优化单手操作体验 - [ ] 视频进一步延迟优化:探索更激进的低延迟策略(如降低帧率、缩小分辨率、调整 ExoPlayer 缓冲策略等) diff --git a/app/src/main/java/com/example/m20_gamepad/MainActivity.kt b/app/src/main/java/com/example/m20_gamepad/MainActivity.kt index deb8edf..57f6ff0 100644 --- a/app/src/main/java/com/example/m20_gamepad/MainActivity.kt +++ b/app/src/main/java/com/example/m20_gamepad/MainActivity.kt @@ -6,6 +6,8 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @@ -18,6 +20,11 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() + // 隐藏系统状态栏,顶部区域完全由自定义 StatusBar 接管 + WindowInsetsControllerCompat(window, window.decorView).apply { + hide(WindowInsetsCompat.Type.statusBars()) + systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } setContent { M20_gamepadTheme { AppNavGraph() diff --git a/app/src/main/java/com/example/m20_gamepad/ui/MainScreen.kt b/app/src/main/java/com/example/m20_gamepad/ui/MainScreen.kt index 51a9a79..84f7f42 100644 --- a/app/src/main/java/com/example/m20_gamepad/ui/MainScreen.kt +++ b/app/src/main/java/com/example/m20_gamepad/ui/MainScreen.kt @@ -2,6 +2,7 @@ package com.example.m20_gamepad.ui import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -14,7 +15,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.rememberScrollState @@ -134,9 +134,14 @@ fun MainScreen( wifiSignalLevel = wifiSignalLevel, onStatusClick = { statusPanelVisible = true }, onSettingsClick = onSettingsClick, - modifier = Modifier - .align(Alignment.TopCenter) - .windowInsetsPadding(WindowInsets.statusBars) + onConnectToggle = { + if (connectionState == ProtocolClient.State.CONNECTED) { + viewModel.disconnect() + } else { + viewModel.connect() + } + }, + modifier = Modifier.align(Alignment.TopCenter) ) // ---- 底部控制区 ---- @@ -180,19 +185,24 @@ private fun StatusBar( wifiSignalLevel: Int, onStatusClick: () -> Unit, onSettingsClick: () -> Unit, + onConnectToggle: () -> Unit, modifier: Modifier = Modifier ) { - Row( + Box( modifier = modifier .fillMaxWidth() .background(OverlayBg) - .padding(horizontal = 12.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { // 连接状态 + WiFi 信号 + Ping 延迟 Row(verticalAlignment = Alignment.CenterVertically) { - ConnectionIndicator(connectionState) + ConnectionIndicator(connectionState, onConnectToggle) Spacer(Modifier.width(12.dp)) WifiSignalIcon(level = wifiSignalLevel) Spacer(Modifier.width(12.dp)) @@ -231,10 +241,11 @@ private fun StatusBar( } } } + } } @Composable -private fun ConnectionIndicator(state: ProtocolClient.State) { +private fun ConnectionIndicator(state: ProtocolClient.State, onClick: () -> Unit) { val (color, text) = when (state) { ProtocolClient.State.CONNECTED -> Color(0xFF4CAF50) to "已连接" ProtocolClient.State.CONNECTING -> Color(0xFFFFC107) to "连接中" @@ -242,14 +253,24 @@ private fun ConnectionIndicator(state: ProtocolClient.State) { ProtocolClient.State.ERROR -> Color(0xFFF44336) to "错误" ProtocolClient.State.DISCONNECTED -> Color(0xFF9E9E9E) to "未连接" } - Row(verticalAlignment = Alignment.CenterVertically) { - Box( - modifier = Modifier - .size(10.dp) - .background(color, CircleShape) - ) - Spacer(Modifier.width(6.dp)) - Text(text, color = OverlayText, fontSize = 14.sp) + Surface( + onClick = onClick, + shape = RoundedCornerShape(14.dp), + border = BorderStroke(1.dp, Color(0x55FFFFFF)), + color = Color(0x22000000) + ) { + Row( + modifier = Modifier.padding(horizontal = 10.dp, vertical = 2.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(10.dp) + .background(color, CircleShape) + ) + Spacer(Modifier.width(6.dp)) + Text(text, color = OverlayText, fontSize = 14.sp) + } } } @@ -376,19 +397,6 @@ private fun ControlButtons( .verticalScroll(scrollState) .padding(top = 4.dp, bottom = 4.dp) ) { - // 连接/断开 - Button( - onClick = { - if (connected) viewModel.disconnect() else viewModel.connect() - }, - colors = ButtonDefaults.buttonColors( - containerColor = if (connected) Color(0xFFF44336) else Color(0xFF4CAF50) - ), - modifier = Modifier.width(110.dp) - ) { - Text(if (connected) "断开" else "连接") - } - // 运动状态转换 ControlButton( "起立",