Flutter&OpenHarmony文件夹管理功能实现

前言

文件夹管理是笔记应用中组织内容的基础功能之一。通过文件夹,用户可以将相关的笔记归类存放,形成清晰的层级结构。一个优秀的文件夹管理系统应该支持创建、重命名、删除、移动等基本操作,同时提供直观的树形结构展示。本文将详细介绍如何在Flutter和OpenHarmony平台上实现完善的文件夹管理功能,帮助用户更好地组织和管理笔记内容。

Flutter文件夹列表展示

文件夹列表通常以树形结构展示,支持展开和折叠操作。

dart 复制代码
class FolderItem extends StatefulWidget {
  final Folder folder;
  final int depth;
  
  const FolderItem({required this.folder, this.depth = 0});
  
  @override
  _FolderItemState createState() => _FolderItemState();
}

class _FolderItemState extends State<FolderItem> {
  bool _isExpanded = false;
}

文件夹项组件需要维护展开状态,使用StatefulWidget来管理这个状态。depth参数表示文件夹的层级深度,用于计算缩进距离。这种递归的组件设计可以支持任意深度的文件夹嵌套,非常适合展示树形结构的数据。通过_isExpanded状态变量控制子文件夹的显示和隐藏。

dart 复制代码
Widget build(BuildContext context) {
  return Column(
    children: [
      InkWell(
        onTap: () {
          if (widget.folder.children.isNotEmpty) {
            setState(() => _isExpanded = !_isExpanded);
          }
        },
        child: Padding(
          padding: EdgeInsets.only(left: widget.depth * 20.0),
          child: Row(
            children: [
              Icon(
                _isExpanded ? Icons.folder_open : Icons.folder,
                color: Colors.amber,
              ),
              SizedBox(width: 8),
              Text(widget.folder.name),
              Spacer(),
              if (widget.folder.children.isNotEmpty)
                Icon(_isExpanded ? Icons.expand_less : Icons.expand_more),
            ],
          ),
        ),
      ),
      if (_isExpanded)
        ...widget.folder.children.map((child) => FolderItem(
          folder: child,
          depth: widget.depth + 1,
        )),
    ],
  );
}

文件夹项的构建使用Column包裹当前文件夹和子文件夹列表。padding根据depth计算左侧缩进,形成层级视觉效果。文件夹图标根据展开状态显示不同的样式,展开时显示打开的文件夹图标。如果有子文件夹,右侧显示展开/折叠箭头。当_isExpanded为true时,递归渲染子文件夹列表,每个子文件夹的depth加1,形成递增的缩进效果。

OpenHarmony文件夹展示

typescript 复制代码
@Component
struct FolderTreeItem {
  @Prop folder: FolderData
  @Prop depth: number = 0
  @State isExpanded: boolean = false
  
  build() {
    Column() {
      Row() {
        Image(this.isExpanded ? $r('app.media.folder_open') : $r('app.media.folder'))
          .width(24)
          .height(24)
        Text(this.folder.name)
          .fontSize(14)
          .margin({ left: 8 })
        Blank()
        if (this.folder.children.length > 0) {
          Image(this.isExpanded ? $r('app.media.arrow_up') : $r('app.media.arrow_down'))
            .width(16)
            .height(16)
        }
      }
      .width('100%')
      .padding({ left: this.depth * 20, top: 12, bottom: 12, right: 12 })
      .onClick(() => {
        if (this.folder.children.length > 0) {
          this.isExpanded = !this.isExpanded
        }
      })
    }
  }
}

OpenHarmony的文件夹项组件使用@Component装饰器定义。@Prop接收父组件传递的数据,@State管理组件内部状态。Row组件水平排列文件夹图标、名称和展开箭头。padding的left值根据depth计算,实现层级缩进效果。Blank组件填充中间空白区域,使箭头图标靠右显示。onClick事件处理点击操作,切换展开状态。

typescript 复制代码
if (this.isExpanded) {
  ForEach(this.folder.children, (child: FolderData) => {
    FolderTreeItem({ folder: child, depth: this.depth + 1 })
  })
}

子文件夹的渲染使用条件判断和ForEach循环。当isExpanded为true时,遍历children数组递归创建FolderTreeItem组件。每个子组件的depth参数加1,形成递增的缩进层级。这种递归渲染的方式可以支持任意深度的文件夹结构,代码简洁且易于维护。

创建文件夹功能

创建文件夹是文件夹管理的基本操作。

dart 复制代码
void _showCreateFolderDialog({Folder? parent}) {
  final controller = TextEditingController();
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: Text('新建文件夹'),
      content: TextField(
        controller: controller,
        autofocus: true,
        decoration: InputDecoration(
          hintText: '请输入文件夹名称',
          border: OutlineInputBorder(),
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: Text('取消'),
        ),
        ElevatedButton(
          onPressed: () {
            if (controller.text.isNotEmpty) {
              _createFolder(controller.text, parent);
              Navigator.pop(context);
            }
          },
          child: Text('创建'),
        ),
      ],
    ),
  );
}

创建文件夹使用对话框收集用户输入的文件夹名称。autofocus设置为true使输入框自动获取焦点,方便用户直接输入。parent参数指定父文件夹,如果为null则在根目录创建。创建按钮的点击处理中先验证输入不为空,然后调用_createFolder方法执行创建操作,最后关闭对话框。这种交互流程简洁明了,用户可以快速完成文件夹创建。

OpenHarmony创建文件夹

typescript 复制代码
@CustomDialog
struct CreateFolderDialog {
  controller: CustomDialogController
  @State folderName: string = ''
  onConfirm: (name: string) => void = () => {}
  
  build() {
    Column() {
      Text('新建文件夹')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })
      
      TextInput({ placeholder: '请输入文件夹名称' })
        .width('100%')
        .height(40)
        .onChange((value: string) => {
          this.folderName = value
        })
      
      Row() {
        Button('取消')
          .backgroundColor('#F0F0F0')
          .fontColor('#333333')
          .onClick(() => {
            this.controller.close()
          })
        Button('创建')
          .backgroundColor('#1890FF')
          .fontColor('#FFFFFF')
          .onClick(() => {
            if (this.folderName.length > 0) {
              this.onConfirm(this.folderName)
              this.controller.close()
            }
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceAround)
      .margin({ top: 20 })
    }
    .padding(20)
    .width(300)
  }
}

OpenHarmony的自定义对话框使用@CustomDialog装饰器。onConfirm是一个回调函数,用于将用户输入的文件夹名称传递给父组件。TextInput组件收集用户输入,onChange回调实时更新folderName状态。创建按钮的点击处理中验证输入不为空后调用onConfirm回调,然后关闭对话框。按钮使用不同的背景色区分取消和确认操作,提供清晰的视觉引导。

文件夹操作菜单

文件夹的重命名、删除、移动等操作通常通过长按菜单实现。

dart 复制代码
PopupMenuButton<String>(
  onSelected: (value) {
    switch (value) {
      case 'rename':
        _showRenameDialog(folder);
        break;
      case 'delete':
        _showDeleteConfirmDialog(folder);
        break;
      case 'move':
        _showMoveFolderDialog(folder);
        break;
    }
  },
  itemBuilder: (context) => [
    PopupMenuItem(value: 'rename', child: Text('重命名')),
    PopupMenuItem(value: 'delete', child: Text('删除')),
    PopupMenuItem(value: 'move', child: Text('移动到...')),
  ],
)

PopupMenuButton提供了便捷的弹出菜单功能。itemBuilder定义菜单项列表,每个菜单项有一个value用于标识操作类型。onSelected回调根据选择的value执行相应的操作。重命名操作打开重命名对话框,删除操作需要先确认,移动操作打开文件夹选择器。这种设计将多个操作收纳在一个菜单中,保持界面的简洁性。

总结

文件夹管理功能是笔记应用中组织内容的重要工具。通过树形结构展示、创建、重命名、删除、移动等功能的实现,用户可以灵活地组织笔记内容。Flutter和OpenHarmony都提供了构建这些功能所需的基础组件,开发者需要合理设计数据结构和交互流程,为用户提供直观易用的文件夹管理体验。

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

相关推荐
半个落月23 分钟前
LangSmith 全链路观测(上):用 LangGraph 与 Milvus 构建可追踪的 RAG 客服
javascript·langchain
半个落月1 小时前
LangChain.js Agent 中间件实战:生命周期、动态工具与文件权限
javascript·langchain
志尊宝2 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
geovindu4 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
程序员老刘6 小时前
Flutter你看看人家RN
flutter·react native·ai编程
知之则吱吱6 小时前
Android 开发者验证机制迎来新变化:核心要求、实施时间与开发者应对指南
android·google
墨天梦7 小时前
D09_Retrofit接口与数据转换
android·kotlin·retrofit
电商API_180079052478 小时前
闲鱼商品列表API接口商品详情API接口请求示例(含一份真实响应数据示例)
android·数据挖掘·网络爬虫·跨境电商·反向海淘
bmxy小明同学8 小时前
2026-10-11-幻觉治理
服务器·前端·javascript
我命由我123458 小时前
Android 广播 - 组件通信
android·java·开发语言·android studio·android jetpack·android-studio·android runtime