在这里插入图片描述

概述

通知设置是视力保护提醒应用中的一个重要功能,它允许用户自定义通知的方式和时间。本文将详细讲解如何实现一个完整的通知设置页面,包括通知类型选择、夜间勿扰设置等功能。

通知设置的核心功能

通知设置页面主要包含以下几个部分:

  1. 通知类型 - 包括声音提醒、振动提醒、弹窗提醒
  2. 夜间勿扰 - 设置夜间勿扰的开始和结束时间
  3. 通知优先级 - 设置不同类型通知的优先级

这些功能结合在一起,为用户提供了一个完整的通知管理界面。

项目依赖配置

在pubspec.yaml中,我们已经配置了所需的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_screenutil: ^5.9.0

flutter_screenutil用于屏幕适配。这些依赖都是为了支持鸿蒙系统的Flutter开发。

通知设置页面实现

页面结构设计

通知设置页面采用StatefulWidget,因为我们需要管理多个开关的状态。页面分为两个主要部分:通知类型和夜间勿扰设置。

class NotificationSettingsDetail extends StatefulWidget {
  const NotificationSettingsDetail({super.key});

  
  State<NotificationSettingsDetail> createState() => _NotificationSettingsDetailState();
}

NotificationSettingsDetail是一个无状态的Widget类,用于创建通知设置页面。通过继承StatefulWidget,我们可以在页面中管理多个开关的状态。createState方法返回对应的State类实例。使用StatefulWidget可以让我们在用户改变设置时实时更新UI。这种设计模式是Flutter中处理有状态UI的标准方式。

状态管理初始化

在_NotificationSettingsDetailState中,我们定义了多个布尔变量来管理各个开关的状态。

class _NotificationSettingsDetailState extends State<NotificationSettingsDetail> {
  bool _soundEnabled = true;
  bool _vibrationEnabled = true;
  bool _popupEnabled = true;
  bool _quietHoursEnabled = false;

这些变量分别表示声音提醒、振动提醒、弹窗提醒和夜间勿扰是否启用。初始值设置为合理的默认值。_soundEnabled_vibrationEnabled_popupEnabled初始值为true,表示默认启用这些通知方式。_quietHoursEnabled初始值为false,表示默认不启用夜间勿扰。这种设计确保了用户首次使用应用时能够收到通知。

主构建方法


Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('通知设置'),
      backgroundColor: const Color(0xFF2196F3),
      foregroundColor: Colors.white,
    ),
    body: SingleChildScrollView(
      child: Column(
        children: [
          _buildNotificationSection(),
          SizedBox(height: 16.h),
          _buildQuietHoursSection(),
          SizedBox(height: 20.h),
        ],
      ),
    ),
  );
}

build方法是Widget的核心,返回整个页面的UI结构。Scaffold提供了Material Design的基本框架,包括AppBar和body。AppBar显示页面标题"通知设置",使用蓝色背景和白色文字。SingleChildScrollView包装了主体内容,确保当内容超过屏幕高度时可以滚动。Column竖直排列了通知类型部分、夜间勿扰部分和底部间距。这种分层的UI结构使代码易于理解和维护。

通知类型部分实现

通知类型容器

通知类型部分包含三个开关选项:声音提醒、振动提醒和弹窗提醒。

Widget _buildNotificationSection() {
  return Container(
    margin: EdgeInsets.all(16.w),
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(12.r),
      boxShadow: [
        BoxShadow(
          color: Colors.black.withOpacity(0.1),
          blurRadius: 8,
          offset: const Offset(0, 2),
        ),
      ],
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '通知类型',

_buildNotificationSection方法构建通知类型区域。使用Container创建一个卡片。BoxDecoration定义了卡片的样式,添加了圆角和阴影效果。Column竖直排列标题和多个通知选项。CrossAxisAlignment.start使内容左对齐。这种设计使通知类型选项清晰地展示在卡片中,用户可以快速了解可用的通知方式。

通知选项列表

          style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 12.h),
        _buildNotificationOption('声音提醒', Icons.volume_up, _soundEnabled, (value) {
          setState(() => _soundEnabled = value);
        }),
        _buildNotificationOption('振动提醒', Icons.vibration, _vibrationEnabled, (value) {
          setState(() => _vibrationEnabled = value);
        }),
        _buildNotificationOption('弹窗提醒', Icons.notifications, _popupEnabled, (value) {
          setState(() => _popupEnabled = value);
        }),
      ],
    ),
  );
}

标题使用较大的加粗字体。通过调用_buildNotificationOption方法,为每个通知选项创建对应的UI组件。三个通知选项分别代表声音提醒、振动提醒和弹窗提醒。每个选项都传入对应的图标、当前状态和状态改变回调。当用户改变开关状态时,通过setState更新对应的布尔变量。这种设计提供了清晰的通知选项管理。

通知选项组件

Widget _buildNotificationOption(
  String title,
  IconData icon,
  bool enabled,
  Function(bool) onChanged,
) {
  return Padding(
    padding: EdgeInsets.symmetric(vertical: 8.h),
    child: Row(
      children: [
        Icon(icon, color: const Color(0xFF2196F3), size: 20.sp),
        SizedBox(width: 12.w),
        Expanded(
          child: Text(
            title,
            style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
          ),
        ),
        Switch(
          value: enabled,
          onChanged: onChanged,
          activeColor: const Color(0xFF2196F3),
        ),
      ],
    ),
  );
}

_buildNotificationOption方法构建单个通知选项。使用Row来横向排列图标、标题和开关。Icon组件显示了通知类型的图标,使用蓝色颜色。Expanded使标题占据中间的剩余空间。Switch组件用于切换通知的启用状态。value参数设置开关的当前状态,onChanged回调在用户改变开关状态时触发。activeColor设置开关启用时的颜色为蓝色。这种设计提供了清晰的通知选项显示和交互。

夜间勿扰部分实现

夜间勿扰容器

夜间勿扰部分包含一个主开关和两个时间选择器。

Widget _buildQuietHoursSection() {
  return Container(
    margin: EdgeInsets.symmetric(horizontal: 16.w),
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(12.r),
      boxShadow: [
        BoxShadow(
          color: Colors.black.withOpacity(0.1),
          blurRadius: 8,
          offset: const Offset(0, 2),
        ),
      ],
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,

_buildQuietHoursSection方法构建夜间勿扰区域。使用Container创建一个白色卡片,添加圆角和阴影效果。Column竖直排列标题行和时间选择器。Row使用mainAxisAlignment: MainAxisAlignment.spaceBetween使标题和开关分别显示在行的两端。这种设计使夜间勿扰设置清晰地展示在卡片中,用户可以快速启用或禁用该功能。

夜间勿扰开关和时间选择器

          children: [
            Text(
              '夜间勿扰',
              style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
            ),
            Switch(
              value: _quietHoursEnabled,
              onChanged: (value) {
                setState(() => _quietHoursEnabled = value);
              },
              activeColor: const Color(0xFF2196F3),
            ),
          ],
        ),
        if (_quietHoursEnabled) ...[
          SizedBox(height: 12.h),
          _buildTimeSelector('开始时间', '22:00'),
          SizedBox(height: 12.h),
          _buildTimeSelector('结束时间', '08:00'),
        ],
      ],
    ),
  );
}

标题使用较大的加粗字体。Switch组件用于启用或禁用夜间勿扰。当用户改变开关状态时,通过setState更新_quietHoursEnabled。使用if (_quietHoursEnabled) ...[...]条件来控制时间选择器的显示。当夜间勿扰启用时,时间选择器才会显示。这种条件渲染模式使UI更加简洁,只显示相关的选项。

时间选择器组件

Widget _buildTimeSelector(String label, String time) {
  return Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [
      Text(
        label,
        style: TextStyle(fontSize: 12.sp, fontWeight: FontWeight.w500),
      ),
      Container(
        padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey[300]!, width: 1),
          borderRadius: BorderRadius.circular(8.r),
        ),
        child: Text(
          time,
          style: TextStyle(fontSize: 12.sp, fontWeight: FontWeight.w500),
        ),
      ),
    ],

_buildTimeSelector方法构建单个时间选择器。使用Row来横向排列标签和时间显示。标签使用较小的加粗字体。时间显示使用Container包裹,添加了边框和圆角。Border.all创建了一个灰色边框,borderRadius添加了圆角。这种设计使时间选择器看起来像一个可交互的元素,提高了用户体验。

时间选择器完成

  );
}

时间选择器的完整实现提供了清晰的时间显示。在实际应用中,可以添加GestureDetector来实现点击时间选择器打开时间选择对话框的功能。

屏幕适配处理

在整个页面中,我们使用flutter_screenutil库来处理屏幕适配。.w表示宽度单位,.h表示高度单位,.sp表示字体大小单位。这样可以确保在不同屏幕尺寸的设备上,UI元素的大小和间距都能正确显示。

例如,EdgeInsets.all(16.w)表示四周都有16个宽度单位的边距。TextStyle(fontSize: 16.sp)表示字体大小为16个字体单位。

数据持久化

在实际应用中,通知设置应该保存到本地存储。可以使用SharedPreferences库来实现:

import 'package:shared_preferences/shared_preferences.dart';

void _saveNotificationSettings() async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setBool('soundEnabled', _soundEnabled);
  await prefs.setBool('vibrationEnabled', _vibrationEnabled);
  await prefs.setBool('popupEnabled', _popupEnabled);
  await prefs.setBool('quietHoursEnabled', _quietHoursEnabled);
}

_saveNotificationSettings方法实现了通知设置的保存。首先获取SharedPreferences实例,然后使用setBool方法将各个开关状态保存到本地存储。这样可以确保用户的设置在应用重启后仍然保留。使用async/await语法使异步操作更加清晰易读。

加载设置

void _loadNotificationSettings() async {
  final prefs = await SharedPreferences.getInstance();
  setState(() {
    _soundEnabled = prefs.getBool('soundEnabled') ?? true;
    _vibrationEnabled = prefs.getBool('vibrationEnabled') ?? true;
    _popupEnabled = prefs.getBool('popupEnabled') ?? true;
    _quietHoursEnabled = prefs.getBool('quietHoursEnabled') ?? false;
  });
}

_loadNotificationSettings方法实现了通知设置的加载。首先获取SharedPreferences实例,然后使用getBool方法从本地存储中读取各个开关状态。使用??操作符提供默认值,如果本地存储中没有保存该值,就使用默认值。通过setState更新UI,使加载的设置立即显示在页面上。这种设计确保了用户的设置能够正确地保存和恢复。

条件渲染

在夜间勿扰部分,我们使用if (_quietHoursEnabled)条件来控制时间选择器的显示。这是Flutter中常见的条件渲染模式。

if (_quietHoursEnabled) ...[
  SizedBox(height: 12.h),
  _buildTimeSelector('开始时间', '22:00'),
  SizedBox(height: 12.h),
  _buildTimeSelector('结束时间', '08:00'),
],

使用spread operator (…)可以将列表中的多个Widget展开到Column中。

总结

通知设置页面通过组合多个UI组件,为用户提供了一个完整的通知管理界面。使用Switch组件管理各个开关的状态,使用条件渲染来动态显示时间选择器。通过flutter_screenutil库,我们确保了UI在不同屏幕尺寸上的正确显示。

这个页面的设计遵循了Material Design的设计规范,使用了统一的颜色方案和间距。用户可以方便地自定义通知的方式和时间,提高了应用的易用性。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐