【HarmonyOS 6】使用说明功能:浮动按钮、弹窗与偏好设置

功能概述

在热力图页面(HeatmapPage)中,使用说明功能由三部分协同工作:

  1. 内嵌式使用说明面板 --- 首次进入或开启常驻时,在网格上方展开的引导卡片
  2. 浮动帮助按钮 --- 面板隐藏后出现在右上角的圆形悬浮按钮
  3. AlertDialog 弹窗 --- 点击 ? 按钮后弹出的详细帮助对话框

三者通过两个状态变量联动:showGuide(控制面板显隐)和 showGuideAlways(控制是否常驻)。同时利用 PreferencesManager 将用户选择持久化到本地。


一、状态定义与初始化

typescript 复制代码
@State showGuide: boolean = false        // 是否显示内嵌面板
@State showGuideAlways: boolean = false  // 是否常驻显示

页面加载时调用 loadGuidePreferences() 从本地偏好读取设置:

typescript 复制代码
async aboutToAppear(): Promise<void> {
  await this.loadData()
  await this.loadGuidePreferences()  // 加载使用说明偏好
}

private async loadGuidePreferences(): Promise<void> {
  const hasSeenGuide = await this.preferencesManager.hasSeenGuide()
  this.showGuideAlways = await this.preferencesManager.getShowGuideAlways()

  // 首次使用 或 设置了常驻显示 → 自动展示面板
  if (!hasSeenGuide || this.showGuideAlways) {
    this.showGuide = true

    // 首次查看后标记为"已读",下次不再自动弹出
    if (!hasSeenGuide) {
      await this.preferencesManager.markGuideAsSeen()
    }
  }
}

设计要点

  • 使用双条件判断:首次用户必看;老用户可选择常驻
  • markGuideAsSeen() 只在首次触发一次,之后由 showGuideAlways 接管

二、内嵌式使用说明面板

showGuide === true 时,在网格内容上方渲染一个卡片:

typescript 复制代码
// GridTimeline() Builder 中
if (this.showGuide) {
  Column() {
    // 标题栏:标题 + 关闭按钮
    Row() {
      Text('使用说明')
        .fontSize(this.fs(16))
        .fontWeight(FontWeight.Bold)
        .fontColor($r('app.color.text_primary'))

      Blank()

      Button() { Text('×') ... }
        .backgroundColor(Color.Transparent)
        .onClick(async () => {
          this.showGuide = false
          // 关闭时若开启了常驻,则一并取消
          if (this.showGuideAlways) {
            this.showGuideAlways = false
            await this.preferencesManager.setShowGuideAlways(false)
          }
        })
    }
    .width('100%')
    .margin({ bottom: 8 })

    // 引导条目列表
    Column() {
      Text('• 点击空白格子:快速记录单个时间段')
      Text('• 长按并拖动:选择多个连续时间段')
      Text('• 点击已记录格子:编辑时间块')
      Text('• 左上角白点:标识时间块的起始位置')
      Text('• 金色边框:高质量时间(专注度≥4 且 价值感≥4)')

      Text('提示:可通过右上角 ? 按钮随时查看帮助')
        .fontStyle(FontStyle.Italic)
    }
    .alignItems(HorizontalAlign.Start)
  }
  .width('100%')
  .padding(16)
  .backgroundColor($r('app.color.card_background'))
  .borderRadius(8)
  .margin({ left: 8, right: 8, bottom: 12 })
}

布局要点

要素 实现方式
标题与关闭按钮同行 Row + Blank() 占据中间空间
关闭按钮样式 背景透明、无 padding、仅显示 × 符号
条目左对齐 外层 Column 设置 alignItems(HorizontalAlign.Start)
底部提示区分级 斜体 + 灰色 + 较小字号

关闭逻辑的细节 :点击 × 时,不仅设 showGuide = false,还检查并同步取消常驻状态,保证 UI 和持久化数据一致。


三、浮动帮助按钮

当内嵌面板隐藏时(!this.showGuide),在页面右上角显示一个圆形悬浮按钮:

typescript 复制代码
// build() 方法中的 Stack 布局内
if (!this.showGuide) {
  Button() {
    Text('?')
      .fontSize(this.fs(20))
      .fontWeight(FontWeight.Bold)
      .fontColor(Color.White)
  }
  .width(48)
  .height(48)
  .borderRadius(24)           // 正圆形
  .backgroundColor($r('app.color.primary_color'))
  .position({ x: '100%', y: 70 })       // 锚定右侧,y=70 是日期导航栏高度
  .translate({ x: -68, y: 20 })         // 向左偏移68,向下偏移20
  .shadow({
    radius: 12,
    color: $r('app.color.primary_shadow'),
    offsetX: 0,
    offsetY: 4
  })
  .onClick(() => {
    this.showGuideDialog()
  })
}

定位原理

  • 整个页面使用 Stack 布局,浮动按钮作为叠加层放置
  • position({ x: '100%', y: 70 }) 将按钮锚定到容器右边缘,垂直位置在日期导航栏下方
  • translate({ x: -68, y: 20 }) 微调最终位置:距离右边距 20px,距离导航栏底部 20px(48px按钮宽度 + 20px边距 = 68px)
  • shadow 属性赋予按钮浮起感

互斥显示if (!this.showGuide) 保证面板和按钮不会同时出现。


四、AlertDialog 帮助弹窗

点击 ? 按钮后调用 showGuideDialog() 弹出系统对话框:

typescript 复制代码
private showGuideDialog(): void {
  AlertDialog.show({
    title: '使用说明',
    message: '• 点击空白格子:快速记录单个时间段\n\n' +
             '• 长按并拖动:先长按某个格子,再滑动选择多个连续时间段\n\n' +
             '• 点击已记录格子:编辑时间块\n\n' +
             '• 左上角白点:标识每个时间块的起始位置\n\n' +
             '• 金色边框:高质量时间(专注度≥4 且 价值感≥4)\n\n' +
             '• 左侧时间标签:显示每行的开始时间\n\n' +
             '• 格子颜色:整点格子较深,半点格子较浅',
    primaryButton: {
      value: this.showGuideAlways ? '关闭常驻显示' : '开启常驻显示',
      action: async () => {
        this.showGuideAlways = !this.showGuideAlways
        await this.preferencesManager.setShowGuideAlways(this.showGuideAlways)
        this.showGuide = this.showGuideAlways  // 开启时常驻显示面板
      }
    },
    secondaryButton: {
      value: '知道了',
      action: () => {}  // 仅关闭对话框
    },
    alignment: DialogAlignment.Center
  })
}

关键设计

  1. 动态按钮文案:主按钮文字根据当前状态切换------"开启常驻显示" ↔ "关闭常驻显示"
  2. 双操作合一 :点击主按钮同时完成:切换状态 → 持久化 → 控制 showGuide(开启时同步显示面板)
  3. \n\n 分段:在 message 中使用双换行实现段落间距

五、偏好设置持久化

PreferencesManager 提供四个 API 管理使用说明状态:

typescript 复制代码
// PreferencesManager.ets 中相关方法

private static readonly KEY_HAS_SEEN_GUIDE: string = 'has_seen_guide'
private static readonly KEY_SHOW_GUIDE_ALWAYS: string = 'show_guide_always'

// 检查是否首次查看
async hasSeenGuide(): Promise<boolean> {
  return await this.prefs.get(KEY_HAS_SEEN_GUIDE, false) as boolean
}

// 标记为已查看(只执行一次)
async markGuideAsSeen(): Promise<void> {
  await this.prefs.put(KEY_HAS_SEEN_GUIDE, true)
  await this.prefs.flush()
}

// 获取常驻显示设置
async getShowGuideAlways(): Promise<boolean> {
  return await this.prefs.get(KEY_SHOW_GUIDE_ALWAYS, false) as boolean
}

// 切换常驻显示
async setShowGuideAlways(show: boolean): Promise<void> {
  await this.pfs.put(KEY_SHOW_GUIDE_ALWAYS, show)
  await this.prefs.flush()
}

首次启动时在 setDefaultPreferences() 中写入默认值:

typescript 复制代码
await this.prefs.put(KEY_HAS_SEEN_GUIDE, false)       // 默认未查看
await this.prefs.put(KEY_SHOW_GUIDE_ALWAYS, false)     // 默认非常驻

底层使用 HarmonyOS 的 @ohos.data.preferences 轻量级 KV 存储,flush() 保证立即写入磁盘。

相关推荐
2501_920627612 小时前
Flutter 框架跨平台鸿蒙开发 - 数学学习助手
学习·flutter·华为·harmonyos
2501_920627612 小时前
Flutter 框架跨平台鸿蒙开发 - 计算器增强版
flutter·华为·harmonyos
2501_920627612 小时前
Flutter 框架跨平台鸿蒙开发 - 单词卡记忆
flutter·华为·harmonyos
芙莉莲教你写代码2 小时前
Flutter 框架跨平台鸿蒙开发 - 宝石消除游戏
flutter·游戏·华为·harmonyos
不愿透露姓名的大鹏17 小时前
华为存储新增LUN存储到VMware集群
运维·服务器·华为·vmware·存储
lxysbly17 小时前
鸿蒙gba模拟器app下载
华为·harmonyos
左手厨刀右手茼蒿18 小时前
Flutter 三方库 firebase_admin 跨云边管线企业级鸿蒙管控底座适配风云:无障碍贯穿服务器授权防火墙打通底层生态授权域并构建海量设备推送集结-适配鸿蒙 HarmonyOS ohos
服务器·flutter·harmonyos
钛态18 小时前
Flutter for OpenHarmony:shelf_web_socket 快速构建 WebSocket 服务端,实现端到端实时通信(WebSocket 服务器) 深度解析与鸿蒙适配指南
服务器·前端·websocket·flutter·华为·性能优化·harmonyos
亚历克斯神18 小时前
Flutter 三方库 at_server_status 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、实时的 @protocol 去中心化身份服务器状态感知与鉴权监控引擎
flutter·华为·harmonyos