【Day7-10】开源鸿蒙之Flutter 的自定义组件封装(1)

Flutter 自定义组件的基本概念

自定义组件是 Flutter 中通过组合现有组件或从头构建新组件的方式实现特定功能。通常通过继承 StatelessWidgetStatefulWidget 实现,前者用于无状态组件,后者用于需要动态更新的组件。

创建无状态自定义组件

无状态组件继承 StatelessWidget,通过 build 方法返回一个组件树。适合静态展示内容。

dart 复制代码
class CustomButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;

  const CustomButton({required this.text, required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text(text),
    );
  }
}

创建有状态自定义组件

有状态组件继承 StatefulWidget,并搭配一个 State 类管理动态数据。通过 setState 触发界面更新。

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

  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('Increment'),
        ),
      ],
    );
  }
}

组合现有组件构建复杂 UI

通过组合 RowColumnContainer 等基础组件,实现更复杂的自定义组件。

dart 复制代码
class CustomCard extends StatelessWidget {
  final String title;
  final String description;

  const CustomCard({required this.title, required this.description});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(title, style: Theme.of(context).textTheme.headline6),
            const SizedBox(height: 8),
            Text(description),
          ],
        ),
      ),
    );
  }
}

使用参数化设计提高复用性

通过构造函数传递参数(如颜色、尺寸、回调函数),使组件更灵活。

dart 复制代码
class CustomIconButton extends StatelessWidget {
  final IconData icon;
  final Color color;
  final VoidCallback onPressed;

  const CustomIconButton({
    required this.icon,
    this.color = Colors.blue,
    required this.onPressed,
  });

  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: Icon(icon, color: color),
      onPressed: onPressed,
    );
  }
}

注意事项

  • 性能优化 :避免在 build 方法中执行耗时操作,将复杂逻辑移至 initState 或异步函数。
  • 主题一致性 :使用 Theme.of(context) 获取全局样式,保持应用风格统一。
  • 文档注释 :为自定义组件添加 /// 文档注释,说明用途和参数含义。

一、添加 UI 组件

在进行自定义组件的封装之前,应该先掌握如何在 Flutter 应用页面中添加内置组件,如按钮和文本等,以下面的页面定义为例:

复制代码
import 'package:flutter/material.dart';

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text("Hello Word!");
  }
}

由于 dart 语法规定了方法返回值只能一个,所以无法通过简单地返回多个 Text 组件,去完成页面内容的增加;而作为 UI 组件,也不支持像字符串那样通过操作符 + 进行内容的拼接,因此,想要上述代码对应的页面具有更多的内容,可行的方法就是使用容器类组件作为最终的返回值,例如下面:

java 复制代码
import 'package:flutter/material.dart';

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text("文本一"),
        Text("文本二"),
      ],
    );
  }
}

又或者:

java 复制代码
import 'package:flutter/material.dart';

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text("文本一"),
        Text("文本二"),
      ],
    );
  }
}

然而,即便是容器组件,也不意味着就能够一次添加多个UI元素,因为像 Container 这种容器组件,只能声明定义一个UI元素:

java 复制代码
class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: (MediaQuery.of(context).size.width*0.95),
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: [
          Text("Hello World"),
          Text("Hello World"),
          Text("Hello World"),
        ],
      ),
    );
  }
}

仔细对比 Container 组件和 Column 组件与 Row 组件的属性,就不难发现可以通过属性名称,去判断一个容器组件是支持多元素定义、还是单一元素定义。

对于像 Column、Row 和 ListView 等支持多元素定义的容器组件,都是用 children 作为属性名,而对于像 Container、Padding 和 Center 等支持单一元素定义的容器组件,则是用 child 作为属性名。

参考文章

学习封装Flutter组件,看这篇就够了

相关推荐
l***749440 分钟前
开源模型应用落地-工具使用篇-Spring AI-Function Call(八)
人工智能·spring·开源
勇气要爆发2 小时前
【第五阶段—高级特性和架构】第六章:自定义Widget开发指南
flutter
白茶三许5 小时前
【2025】Flutter 卡片组件封装与分页功能实现:实战指南
flutter·开源·openharmony
Bervin121385 小时前
Flutter Android环境的搭建
android·flutter
十六年开源服务商10 小时前
房地产WordPress系统最佳解决方案
开源
空白诗11 小时前
mdcat 在 HarmonyOS 上的构建与适配
后端·安全·华为·rust·harmonyos
百***354811 小时前
HarmonyOS在智能办公中的文档协作
华为·harmonyos
Days205012 小时前
童梦奇缘博客主题已发布
开源
fouryears_2341713 小时前
现代 Android 后台应用读取剪贴板最佳实践
android·前端·flutter·dart