请添加图片描述

编辑书籍页面和添加页面很像,但需要回显已有数据,还要支持删除功能。今天来实现这个页面,主要涉及数据回显、评分修改、删除确认等功能。

编辑页面比添加页面多了几个功能:回显已有数据、修改评分、删除书籍。这些功能让用户可以完整地管理自己的书籍信息。

页面整体结构

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';

class EditBookPage extends StatefulWidget {
  const EditBookPage({super.key});
  
  State<EditBookPage> createState() => _EditBookPageState();
}

和添加页面一样用 StatefulWidget,因为有表单状态需要管理。

状态变量和控制器

class _EditBookPageState extends State<EditBookPage> {
  final _formKey = GlobalKey<FormState>();
  String _status = '在读';
  String _category = '文学';
  final _titleController = TextEditingController(text: '百年孤独');
  final _authorController = TextEditingController(text: '加西亚·马尔克斯');
  final _publisherController = TextEditingController(text: '南海出版公司');
  final _pagesController = TextEditingController(text: '380');

和添加页面不同的是,这里用 TextEditingController 来控制输入框的值,并且在初始化时就填入已有数据。实际项目中这些数据应该从路由参数或数据库获取。

生命周期管理

  
  void dispose() {
    _titleController.dispose();
    _authorController.dispose();
    _publisherController.dispose();
    _pagesController.dispose();
    super.dispose();
  }

TextEditingController 需要在 dispose 中销毁,防止内存泄漏。这是 Flutter 开发的基本规范。

AppBar 配置

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFFDF8F3),
      appBar: AppBar(
        title: const Text('编辑书籍'),
        backgroundColor: const Color(0xFF5B4636),
        foregroundColor: Colors.white,
        actions: [
          IconButton(icon: const Icon(Icons.delete_outline), onPressed: () => _showDeleteDialog()),
        ],
      ),

右上角放了删除按钮,点击后弹出确认对话框。删除是危险操作,需要二次确认。

页面内容布局

      body: SingleChildScrollView(
        padding: EdgeInsets.all(16.w),
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              _buildCoverSection(),
              SizedBox(height: 20.h),
              _buildFormSection(),
              SizedBox(height: 20.h),
              _buildStatusSection(),
              SizedBox(height: 20.h),
              _buildRatingSection(),
              SizedBox(height: 30.h),
              _buildSubmitButton(),
            ],
          ),
        ),
      ),
    );
  }

比添加页面多了一个评分模块,因为编辑时用户可能想修改自己对这本书的评分。

封面编辑区域

  Widget _buildCoverSection() {
    return Center(
      child: Stack(
        children: [
          Container(
            width: 120.w, height: 160.h,
            decoration: BoxDecoration(
              color: const Color(0xFF5B4636).withOpacity(0.1),
              borderRadius: BorderRadius.circular(12.r),
            ),
            child: Icon(Icons.menu_book, size: 60.sp, color: const Color(0xFF5B4636)),
          ),
          Positioned(
            right: 0, bottom: 0,
            child: Container(
              padding: EdgeInsets.all(6.w),
              decoration: const BoxDecoration(color: Color(0xFF5B4636), shape: BoxShape.circle),
              child: Icon(Icons.camera_alt, size: 16.sp, color: Colors.white),
            ),
          ),
        ],
      ),
    );
  }

封面区域用 Stack 叠加一个相机图标,表示可以更换封面。和添加页面的虚线框不同,这里显示的是已有的封面(用图标代替)。

表单输入区域

  Widget _buildFormSection() {
    return Container(
      padding: EdgeInsets.all(16.w),
      decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12.r)),
      child: Column(
        children: [
          _buildTextField('书名', _titleController, Icons.menu_book),
          SizedBox(height: 16.h),
          _buildTextField('作者', _authorController, Icons.person),
          SizedBox(height: 16.h),
          _buildTextField('出版社', _publisherController, Icons.business),
          SizedBox(height: 16.h),
          _buildTextField('总页数', _pagesController, Icons.format_list_numbered, keyboardType: TextInputType.number),
          SizedBox(height: 16.h),
          _buildDropdown('分类', _category, ['文学', '历史', '科技', '经济', '哲学', '心理', '艺术', '其他'], (v) => setState(() => _category = v!)),
        ],
      ),
    );
  }

表单字段和添加页面类似,但输入框绑定了 TextEditingController,会自动显示已有数据。

文本输入组件

  Widget _buildTextField(String label, TextEditingController controller, IconData icon, {TextInputType? keyboardType}) {
    return TextFormField(
      controller: controller,
      keyboardType: keyboardType,
      decoration: InputDecoration(
        labelText: label,
        prefixIcon: Icon(icon, color: const Color(0xFF5B4636)),
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(8.r)),
        focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8.r), borderSide: const BorderSide(color: Color(0xFF5B4636), width: 2)),
      ),
    );
  }

和添加页面的区别是这里接收 TextEditingController 而不是 hint 文字。

评分修改模块

  Widget _buildRatingSection() {
    return Container(
      padding: EdgeInsets.all(16.w),
      decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12.r)),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('我的评分', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold, color: const Color(0xFF3D2914))),
          SizedBox(height: 12.h),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: List.generate(5, (i) => GestureDetector(
              onTap: () {},
              child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 4.w),
                child: Icon(i < 4 ? Icons.star : Icons.star_border, color: Colors.amber, size: 36.sp),
              ),
            )),
          ),
        ],
      ),
    );
  }

评分用五颗星显示,点击可以修改评分。星星比较大(36.sp),方便点击。实心星表示已评分,空心星表示未评分。

提交按钮

  Widget _buildSubmitButton() {
    return SizedBox(
      width: double.infinity,
      child: ElevatedButton(
        onPressed: () { Get.back(); Get.snackbar('成功', '书籍信息已更新'); },
        style: ElevatedButton.styleFrom(
          backgroundColor: const Color(0xFF5B4636), 
          foregroundColor: Colors.white, 
          padding: EdgeInsets.symmetric(vertical: 16.h), 
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r))
        ),
        child: Text('保存修改', style: TextStyle(fontSize: 16.sp)),
      ),
    );
  }

按钮文字改成"保存修改",和添加页面的"保存"区分开。

删除确认对话框

  void _showDeleteDialog() {
    Get.dialog(AlertDialog(
      title: const Text('删除书籍'),
      content: const Text('确定要删除这本书吗?相关的阅读记录和笔记也会被删除。'),
      actions: [
        TextButton(onPressed: () => Get.back(), child: const Text('取消')),
        TextButton(
          onPressed: () { Get.back(); Get.back(); Get.snackbar('已删除', '书籍已删除'); }, 
          child: const Text('删除', style: TextStyle(color: Colors.red))
        ),
      ],
    ));
  }
}

删除对话框提醒用户相关数据也会被删除,让用户做出知情决定。确认按钮用红色文字强调危险性。

Get.back() 调用两次:第一次关闭对话框,第二次返回上一页。

数据回显的实现

实际项目中,编辑页面的数据应该从路由参数获取:

// 示例:从路由参数获取书籍ID
// final bookId = Get.arguments['id'];
// 然后从数据库查询书籍信息
// final book = await db.getBook(bookId);
// 再用 setState 更新控制器的值

目前数据是写死的,后面接入数据库时再改。

编辑和添加的区别

编辑页面和添加页面的主要区别:

数据回显:编辑页面需要显示已有数据,添加页面是空白的。

删除功能:编辑页面有删除按钮,添加页面没有。

评分功能:编辑页面可以修改评分,添加页面通常不需要评分(还没读呢)。

按钮文字:编辑是"保存修改",添加是"保存"。

小结

编辑书籍页面在添加页面的基础上增加了数据回显、评分修改、删除功能。用 TextEditingController 控制输入框的值,用对话框确认删除操作。

下一篇会讲书架列表页面的实现,涉及到网格布局和颜色选择,敬请期待。


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

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐