# 02 — 交互流程与导航设计 > **核心原则**:间接启动(语音/手势)不进入全屏 APP,而是以悬浮覆盖层呈现 > **关联文档**:[01-voice-assistant-system.md](01-voice-assistant-system.md) --- ## 1. 启动来源 → 界面模式 映射表 ``` ┌──────────────────────────────────────────────────────────┐ │ 启动来源 │ ├───────────────────────┬──────────────────────────────────┤ │ 直接启动 (Explicit) │ 间接启动 (Implicit) │ ├───────────────────────┼──────────────────────────────────┤ │ · 桌面图标 │ · 语音唤醒 ("昔涟") │ │ · 最近任务列表 │ · 长按 Home 键 │ │ · 通知栏点击 │ · 底部两角向内滑动 │ │ · Deep Link │ · 长按电源键 (配置后) │ │ │ · 耳机按键 (单击/长按) │ │ │ · 锁屏右滑助手 │ ├───────────────────────┼──────────────────────────────────┤ │ ▼ │ ▼ │ │ 全屏 Activity │ VoiceInteractionSession │ │ (MainActivity) │ (全屏悬浮覆盖层) │ │ · 完整导航栏 │ · 无导航栏 │ │ · Tab 切换 │ · 仅对话卡片 │ │ · 设置/IoT 面板 │ · 半透明遮罩透出底层 │ │ · 压入返回栈 │ · 不压入返回栈 │ └───────────────────────┴──────────────────────────────────┘ ``` ## 2. 全屏 Activity 模式 ### 2.1 导航结构 ``` MainActivity ├── BottomNavigation │ ├── Tab 1: 对话 (ChatScreen) ← 默认页 │ ├── Tab 2: IoT 面板 (IoTScreen) │ └── Tab 3: 我的 (ProfileScreen) ├── TopAppBar │ ├── 昔涟状态指示器 (在线/思考中/离线) │ └── 快捷操作 (设置、通知) └── 子页面 (通过 NavHost 导航) ├── SettingsScreen ├── MemoryScreen (记忆查看) ├── KnowledgeScreen (知识库) ├── AutomationScreen (自动化规则) ├── ReminderScreen (提醒列表) └── LoginScreen ``` ### 2.2 导航图 (NavGraph) ``` LoginScreen ──(登录成功)──► MainScreen (带 BottomNav) │ ┌────────────┼────────────┐ ▼ ▼ ▼ ChatScreen IoTScreen ProfileScreen │ │ ▼ ▼ MemoryScreen SettingsScreen KnowledgeScreen ├─ Account AutomationScreen ├─ Appearance (主题) ReminderScreen ├─ Voice (唤醒词/语音) ├─ IoT Config └─ About ``` ### 2.3 登录流程 ``` APP 首次启动 → 检查本地 Token ├─ 有效 → 直接进入 MainScreen └─ 无效 → LoginScreen ├─ 输入 Gateway 地址 + 账号密码 ├─ POST /api/v1/auth/login ├─ 保存 Token 到 DataStore └─ 进入 MainScreen ``` ## 3. 悬浮覆盖层模式 (VoiceInteractionSession) ### 3.1 视觉层级 ``` ┌──────────────────────────────────────┐ │ 底层 APP (半透明可见) │ │ ┌──────────────────────────────┐ │ │ │ 半透明黑色遮罩 (80% 不透明度) │ │ │ │ │ │ │ │ ┌──────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ 对话卡片区域 │ │ │ │ │ │ (圆角顶部 28dp) │ │ │ │ │ │ │ │ │ │ │ │ · 昔涟状态条 │ │ │ │ │ │ · 对话消息流 │ │ │ │ │ │ · 文本输入框 │ │ │ │ │ │ · 语音输入按钮 │ │ │ │ │ │ │ │ │ │ │ └──────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────┘ │ └──────────────────────────────────────┘ ``` ### 3.2 覆盖层生命周期 ``` Trigger (唤醒词/手势/按键) │ ▼ VoiceInteractionSession.onCreateContentView() │ ▼ onShow() → 设置窗口属性 → 播放出现动画(底部滑入) │ ▼ OverlayScreen Compose 渲染 │ ├→ 用户说话 → STT → 显示识别文本 → 发送到 AI-Core │ │ │ ▼ │ SSE 流式响应 │ │ ├← TTS 语音播放 ←── 流式合成 ←────────────┘ │ ├→ 用户打字输入 → WebSocket 发送 → 显示回复气泡 │ ▼ 对话结束 ├→ 用户主动关闭 (说"再见"/点击遮罩/下滑) └→ 超时自动关闭 (静默 10 秒) │ ▼ onHide() → 播放消失动画(底部滑出) │ ▼ finish() → 返回触发前界面 ``` ### 3.3 覆盖层状态机 ``` ┌──────────┐ │ IDLE │ (覆盖层不可见) └────┬─────┘ │ 触发 ▼ ┌──────────┐ │LISTENING │ (等待语音输入,波形动画) └────┬─────┘ │ 检测到语音 / 用户开始打字 ▼ ┌──────────┐ │PROCESSING│ (STT 识别中 / LLM 思考中) └────┬─────┘ │ 收到回复 ▼ ┌──────────┐ │SPEAKING │ (TTS 播放中) └────┬─────┘ │ 播放完毕,等待下一轮 ▼ ┌──────────┐ │ WAITING │ (等待用户继续或关闭) └────┬─────┘ │ ┌───────┼───────┐ │ │ 用户继续说话 10s 静默 │ │ ▼ ▼ LISTENING IDLE (覆盖层关闭) ``` ### 3.4 与全屏 Activity 的切换 ``` 悬浮窗中用户点击 "打开完整 APP" → finish() 关闭悬浮窗 → startActivity(MainActivity) → 用户在全屏模式下继续操作 全屏 APP 中用户按 Home 返回桌面 → onStop() → 进入后台 → WebSocket 保持连接 → 推送/FCM 通知到达时,点击通知 → 恢复 MainActivity ``` ## 4. 锁屏交互 ### 4.1 锁屏唤醒 ``` 设备锁屏 + 息屏 │ ├→ 说出唤醒词 "昔涟" │ └→ onLaunchVoiceAssistFromKeyguard() │ └→ 简化版覆盖层 (仅对话,无 IoT / 敏感操作) │ └→ 长按电源键 └→ 同理 ``` ### 4.2 锁屏安全策略 | 操作 | 锁屏状态 | 行为 | |------|---------|------| | 查询天气/时间 | 允许 | 直接回复 | | 简单闲聊 | 允许 | 直接回复 | | IoT 查询(状态) | 允许 | 回复设备状态 | | IoT 控制(开关) | **禁止** | 提示"请先解锁设备" | | 查看记忆 | **禁止** | 提示"请先解锁设备" | | 修改设置 | **禁止** | 提示"请先解锁设备" | | 宿主命令 | **禁止** | 提示"请先解锁设备" | ## 5. 多窗口与分屏 - **分屏模式**:悬浮窗模式下不支持(本身已是覆盖层);全屏 Activity 支持分屏 - **画中画**:语音通话场景支持画中画(PIP),显示昔涟头像 + 波形动画 ## 6. 手势交互 | 手势 | 悬浮窗模式 | 全屏 Activity | |------|-----------|---------------| | 下滑覆盖层 | 关闭悬浮窗 | — | | 点击遮罩区域 | 关闭悬浮窗 | — | | 长按消息 | 复制/分享菜单 | 复制/分享/删除 | | 左滑消息 | — | 查看消息详情/时间戳 | | 双击昔涟头像 | 切换输入模式(语音↔文字) | 同左 |