Flutter for OpenHarmony垃圾分类指南App实战:政策法规实现

垃圾分类不是随便分分就行的,背后是有法律法规支撑的。政策法规页面就是让用户了解这些规定,知道垃圾分类是有法可依的,不是可做可不做的事情。

为什么需要这个页面

很多人可能觉得垃圾分类只是一种倡导,做不做无所谓。但实际上,从2017年开始,国家就出台了一系列政策法规来推动垃圾分类工作。了解这些政策有几个好处:

  1. 提高重视程度:知道这是法律要求,不是可选项
  2. 了解处罚标准:知道违规的后果
  3. 理解政策背景:知道为什么要这样分类

这个页面的目标是用简洁的方式呈现这些信息,让用户快速了解政策概况,而不是把整个法规文本都堆上去。

数据结构设计

政策法规的数据包含标题、实施时间和内容摘要:

dart 复制代码
class PolicyPage extends StatelessWidget {
  const PolicyPage({super.key});

  @override
  Widget build(BuildContext context) {
    // 政策法规数据
    // 实际项目中这些数据可能来自后端接口
    final policies = [
      {
        'title': '《生活垃圾分类制度实施方案》',
        'date': '2017年3月',
        'summary': '国务院办公厅发布,要求在全国46个重点城市先行实施生活垃圾强制分类。',
        'level': '国家级',
      },
      {
        'title': '《上海市生活垃圾管理条例》',
        'date': '2019年7月',
        'summary': '上海率先实施垃圾分类,将生活垃圾分为可回收物、有害垃圾、湿垃圾、干垃圾四类。',
        'level': '地方级',
      },

这些都是真实的政策法规,时间线从2017年到2020年,展示了垃圾分类政策的推进过程。

继续看后面的数据:

dart 复制代码
      {
        'title': '《北京市生活垃圾管理条例》',
        'date': '2020年5月',
        'summary': '北京实施垃圾分类,将生活垃圾分为厨余垃圾、可回收物、有害垃圾、其他垃圾四类。',
        'level': '地方级',
      },
      {
        'title': '《固体废物污染环境防治法》',
        'date': '2020年9月',
        'summary': '新修订的固废法明确了生活垃圾分类制度,推动垃圾分类工作法治化。',
        'level': '国家级',
      },
      {
        'title': '《"十四五"城镇生活垃圾分类和处理设施发展规划》',
        'date': '2021年5月',
        'summary': '明确到2025年底,全国城市生活垃圾分类收运能力达到70万吨/日以上。',
        'level': '国家级',
      },
      {
        'title': '《关于进一步推进生活垃圾分类工作的若干意见》',
        'date': '2020年11月',
        'summary': '住建部等12部门联合发布,要求到2025年基本建立配套完善的生活垃圾分类法规制度体系。',
        'level': '国家级',
      },
    ];

内容选择:选了几个有代表性的政策,包括国家层面的方案、地方性法规、以及专门的法律。让用户对政策体系有个整体认识。数据按时间顺序排列,用户可以看到政策是怎么一步步推进的。

页面布局

页面结构包含一个说明区域和政策列表:

dart 复制代码
    return Scaffold(
      appBar: AppBar(title: const Text('政策法规')),
      body: Column(
        children: [
          // 顶部说明区域
          _buildHeader(),
          // 政策列表
          Expanded(
            child: ListView.builder(
              padding: EdgeInsets.all(16.w),
              itemCount: policies.length,
              itemBuilder: (context, index) {
                final policy = policies[index];
                return _buildPolicyCard(policy);
              },
            ),
          ),
        ],
      ),
    );
  }

ListView.builder渲染政策列表,这样即使政策数量很多,也能保持良好的性能。

顶部说明区域

在列表上方加一个说明区域,告诉用户这个页面是干什么的:

dart 复制代码
Widget _buildHeader() {
  return Container(
    margin: EdgeInsets.all(16.w),
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      // 使用浅蓝色背景,表示"信息"
      color: Colors.blue.withOpacity(0.1),
      borderRadius: BorderRadius.circular(12.r),
      border: Border.all(color: Colors.blue.withOpacity(0.3)),
    ),
    child: Row(
      children: [
        Icon(Icons.info_outline, color: Colors.blue, size: 24.sp),
        SizedBox(width: 12.w),
        Expanded(
          child: Text(
            '垃圾分类已纳入法律法规体系,了解相关政策有助于更好地参与垃圾分类工作。',
            style: TextStyle(fontSize: 14.sp, color: Colors.blue.shade700),
          ),
        ),
      ],
    ),
  );
}

这个说明区域用蓝色调,表示这是"信息提示"而不是"警告"。文案简洁明了,告诉用户为什么要了解这些政策。

政策卡片组件

每张卡片包含图标、标题、时间、级别标签和摘要:

dart 复制代码
Widget _buildPolicyCard(Map<String, String> policy) {
  // 根据政策级别确定标签颜色
  final isNational = policy['level'] == '国家级';
  final levelColor = isNational ? Colors.red : Colors.orange;
  
  return Card(
    margin: EdgeInsets.only(bottom: 12.h),
    // 添加轻微阴影
    elevation: 2,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(12.r),
    ),

Card组件包裹每条政策,自带阴影和圆角,看起来比较有层次感。

卡片内容结构:

dart 复制代码
    child: Padding(
      padding: EdgeInsets.all(16.w),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 第一行:图标、标题、级别标签
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 政策图标
              Container(
                width: 40.w,
                height: 40.w,
                decoration: BoxDecoration(
                  color: AppTheme.primaryColor.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(8.r),
                ),
                child: Icon(
                  Icons.policy,
                  color: AppTheme.primaryColor,
                  size: 24.sp,
                ),
              ),
              SizedBox(width: 12.w),
              // 标题和级别标签
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // 标题
                    Text(
                      policy['title']!,
                      style: TextStyle(
                        fontSize: 15.sp,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 4.h),
                    // 级别标签和时间
                    Row(
                      children: [
                        // 级别标签
                        Container(
                          padding: EdgeInsets.symmetric(
                            horizontal: 6.w,
                            vertical: 2.h,
                          ),
                          decoration: BoxDecoration(
                            color: levelColor.withOpacity(0.1),
                            borderRadius: BorderRadius.circular(4.r),
                          ),
                          child: Text(
                            policy['level']!,
                            style: TextStyle(
                              fontSize: 10.sp,
                              color: levelColor,
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                        ),
                        SizedBox(width: 8.w),
                        // 实施时间
                        Text(
                          '实施时间:${policy['date']}',
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ],
          ),

标题前面放了个政策图标,让用户一眼就知道这是官方文件。Expanded包裹标题文字,这样标题太长时会自动换行而不是溢出。

级别标签用不同颜色区分:

  • 国家级:红色,表示最高级别
  • 地方级:橙色,表示地方性法规

接下来是摘要:

dart 复制代码
          SizedBox(height: 12.h),
          // 分隔线
          Divider(height: 1, color: Colors.grey.shade200),
          SizedBox(height: 12.h),
          // 摘要内容
          Text(
            policy['summary']!,
            style: TextStyle(
              fontSize: 14.sp,
              height: 1.6,
              color: Colors.grey.shade700,
            ),
          ),
          SizedBox(height: 8.h),
          // 查看详情按钮
          Align(
            alignment: Alignment.centerRight,
            child: TextButton(
              onPressed: () => _showPolicyDetail(policy),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    '查看详情',
                    style: TextStyle(
                      fontSize: 13.sp,
                      color: AppTheme.primaryColor,
                    ),
                  ),
                  Icon(
                    Icons.arrow_forward,
                    size: 14.sp,
                    color: AppTheme.primaryColor,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    ),
  );
}

摘要用灰色文字显示,行高1.6保证可读性。底部有个"查看详情"按钮,点击可以查看完整的法规内容。

查看详情功能

点击"查看详情"可以弹出一个对话框或跳转到详情页:

dart 复制代码
void _showPolicyDetail(Map<String, String> policy) {
  Get.dialog(
    AlertDialog(
      title: Text(
        policy['title']!,
        style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
      ),
      content: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: [
            // 基本信息
            _buildDetailItem('实施时间', policy['date']!),
            _buildDetailItem('政策级别', policy['level']!),
            SizedBox(height: 12.h),
            // 摘要
            Text(
              '政策摘要',
              style: TextStyle(
                fontSize: 14.sp,
                fontWeight: FontWeight.bold,
              ),
            ),
            SizedBox(height: 8.h),
            Text(
              policy['summary']!,
              style: TextStyle(fontSize: 14.sp, height: 1.6),
            ),
            SizedBox(height: 16.h),
            // 提示
            Container(
              padding: EdgeInsets.all(12.w),
              decoration: BoxDecoration(
                color: Colors.grey.shade100,
                borderRadius: BorderRadius.circular(8.r),
              ),
              child: Text(
                '如需查看完整法规文本,请访问国家或地方政府官方网站。',
                style: TextStyle(
                  fontSize: 12.sp,
                  color: Colors.grey.shade600,
                ),
              ),
            ),
          ],
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Get.back(),
          child: const Text('关闭'),
        ),
      ],
    ),
  );
}

Widget _buildDetailItem(String label, String value) {
  return Padding(
    padding: EdgeInsets.only(bottom: 8.h),
    child: Row(
      children: [
        Text(
          '$label:',
          style: TextStyle(
            fontSize: 14.sp,
            color: Colors.grey,
          ),
        ),
        Text(
          value,
          style: TextStyle(fontSize: 14.sp),
        ),
      ],
    ),
  );
}

设计考量

1. 信息密度适中

每条政策只展示最核心的信息:是什么、什么时候实施、主要内容是什么。不需要把整个法规文本都放进来,那样用户根本不会看。

2. 时间线呈现

数据按时间顺序排列,用户可以看到政策是怎么一步步推进的。从2017年的方案到2020年的法律,垃圾分类从倡导变成了强制。

3. 权威感

用了Icons.policy这个图标,加上书名号包裹的标题,整体给人一种正式、权威的感觉。这和页面的内容性质是匹配的。

4. 层级区分

用颜色标签区分国家级和地方级政策,让用户快速了解政策的层级。

可以扩展的方向

如果要做得更完善,可以考虑:

1. 点击查看详情

跳转到详情页展示完整的法规内容,或者链接到官方网站。

dart 复制代码
void _openPolicyUrl(String url) {
  launchUrl(Uri.parse(url));
}

2. 按地区筛选

用户可以只看自己所在城市的政策:

dart 复制代码
Widget _buildFilterChips() {
  return Wrap(
    spacing: 8.w,
    children: ['全部', '国家级', '上海', '北京', '广州'].map((filter) {
      return FilterChip(
        label: Text(filter),
        selected: _selectedFilter == filter,
        onSelected: (selected) {
          setState(() => _selectedFilter = filter);
        },
      );
    }).toList(),
  );
}

3. 更新提醒

有新政策出台时推送通知:

dart 复制代码
void checkPolicyUpdates() async {
  final newPolicies = await api.getNewPolicies();
  if (newPolicies.isNotEmpty) {
    showNotification('有${newPolicies.length}条新政策发布');
  }
}

4. 收藏功能

用户可以收藏关心的政策:

dart 复制代码
Widget _buildBookmarkButton(String policyId) {
  return Obx(() => IconButton(
    icon: Icon(
      controller.isBookmarked(policyId)
          ? Icons.bookmark
          : Icons.bookmark_border,
    ),
    onPressed: () => controller.toggleBookmark(policyId),
  ));
}

5. 搜索功能

政策多了之后,可以加个搜索框:

dart 复制代码
Widget _buildSearchBar() {
  return TextField(
    onChanged: (value) {
      setState(() {
        _filteredPolicies = policies.where((p) =>
          p['title']!.contains(value) ||
          p['summary']!.contains(value)
        ).toList();
      });
    },
    decoration: InputDecoration(
      hintText: '搜索政策法规',
      prefixIcon: Icon(Icons.search),
    ),
  );
}

数据来源说明

实际项目中,政策数据应该从可靠的来源获取:

  1. 政府官方网站:最权威的来源
  2. 后端接口:由运营人员维护,定期更新
  3. 本地数据库:首次加载后缓存到本地
dart 复制代码
class PolicyRepository {
  // 从后端获取政策列表
  Future<List<Policy>> fetchPolicies() async {
    try {
      final response = await dio.get('/api/policies');
      return (response.data as List)
          .map((json) => Policy.fromJson(json))
          .toList();
    } catch (e) {
      // 网络错误时返回本地缓存
      return _getLocalPolicies();
    }
  }
  
  // 获取本地缓存的政策
  List<Policy> _getLocalPolicies() {
    final data = storage.read('policies');
    if (data != null) {
      return (data as List)
          .map((json) => Policy.fromJson(json))
          .toList();
    }
    return [];
  }
}

这个页面的实现比较简单,但内容很重要。让用户知道垃圾分类是有法律依据的,能提高他们的重视程度。


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

相关推荐
Aktx20FNz8 分钟前
iFlow CLI 完整工作流指南
大数据·elasticsearch·搜索引擎
LaughingZhu1 小时前
Anthropic 收购 Oven 后,Claude Code 用运行时写了一篇护城河文章
大数据·人工智能·经验分享·搜索引擎·语音识别
学习3人组1 小时前
TortoiseGit冲突解决实战上机练习
大数据·elasticsearch·搜索引擎
Ln5x9qZC21 小时前
Flink SQL 元数据持久化实战
大数据·sql·flink
OYpBNTQXi2 小时前
Flink Agents 源码解读 --- (6) --- ActionTask
大数据·flink
中金快讯2 小时前
济民健康医疗服务占比提升至46%!业务结构调整初见成效
大数据·人工智能
lizhihai_992 小时前
股市学习心得-尾盘半小时买入法
大数据
大大大大晴天️3 小时前
Hudi 生产问题排障-乱序Upsert入湖数据丢失
大数据·flink·hudi
程序大视界3 小时前
2026AI智能体元年,中国正式超越美国
大数据·人工智能
qq_235132173 小时前
五金制造行业ERP系统多少钱?易呈erp五金行业版功能模块详解与成功案例分享
大数据·运维·人工智能·制造·智能制造