许多群友询问我关于 ducafe_ui_core 的使用方法。这个组件是我将之前项目中频繁重复使用的功能独立抽取出来,以便在新项目中引入,从而提升开发效率。如果你想系统地学习 Flutter,欢迎关注我的新课程woo2025。在本文中,我将介绍 ducafe_ui_core 包含的各种功能。

我写了个 Flutter 组件 ducafe_ui_core

Flutter 组件 ducafe_ui_core

视频

前言

原文 Flutter 组件 ducafe_ui_core:提升开发效率的利器

许多群友询问我关于 ducafe_ui_core 的使用方法。这个组件是我将之前项目中频繁重复使用的功能独立抽取出来,以便在新项目中引入,从而提升开发效率。如果你想系统地学习 Flutter,欢迎关注我的新课程 woo2025。在本文中,我将介绍 ducafe_ui_core 包含的各种功能。

参考

https://ducafecat.com/course/flutter-woo-2025

https://pub.dev/packages/ducafe_ui_core

功能介绍

添加依赖

https://pub.dev/packages/ducafe_ui_core

pubspec.yaml

dependencies:
  ...

  ducafe_ui_core: ^1.0.6

1 设计稿适配

编辑 lib/main.dart ,初始屏幕适配

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(375, 812),
      builder: (context, child) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      },
    );
  }
}

包裹 ScreenUtilInit

编写 lib/page1.dart

  Widget _buildView() {
    return Container(
      color: Colors.blue,
      width: 300.w,
      height: 300.h,
      child: Column(
        children: [
          Text('Page One'),
        ],
      ),
    );
  }

通过 .w .h 动态适配计算

编辑 lib/main.dart ,跳转到新页面

  void _incrementCounter() {
    // 上下文导航操作
    context.navigator.pushMaterial(const PageOne());

    // 原始写法
    // Navigator.push(
    //     context, MaterialPageRoute(builder: (context) => const PageOne()));
  }

用 web 方式启动,方便测试内容区域尺寸变化

方正屏幕

方正屏幕

又长又矮屏幕

又长又矮屏幕

2 视图层打薄

圆角按钮

打薄后代码

  Widget _buildView() {
    return Text("ducafecat")
        .fontSize(22)
        .alignment(Alignment.center)
        .borderRadius(all: 15)
        .ripple()
        .backgroundColor(Colors.white, animate: true)
        .clipRRect(all: 25) // clip ripple
        .borderRadius(all: 25, animate: true)
        .elevation(
          pressed ? 0 : 1,
          borderRadius: BorderRadius.circular(25),
          shadowColor: Color(0x30000000),
        ) // shadow borderRadius
        .padding(vertical: 12) // margin
        .onTap(
          () => print('onTap'),
        )
        .scale(all: pressed ? 0.95 : 1.0, animate: true)
        .animate(Duration(milliseconds: 150), Curves.easeOut)
        .tight(
          height: 80,
          width: 200,
        )
        .center();
  }

原始方式代码

Widget _buildView() {
  return Center(
    child: GestureDetector(
      onTapDown: (_) => setState(() => pressed = true),
      onTapUp: (_) => setState(() => pressed = false),
      onTapCancel: () => setState(() => pressed = false),
      child: AnimatedContainer(
        duration: Duration(milliseconds: 150),
        curve: Curves.easeOut,
        height: 80,
        width: 200,
        transform: Matrix4.identity()..scale(pressed ? 0.95 : 1.0),
        child: Material(
          color: Colors.white,
          elevation: pressed ? 0 : 1,
          shadowColor: Color(0x30000000),
          borderRadius: BorderRadius.circular(25),
          child: InkWell(
            onTap: () => print('onTap'),
            borderRadius: BorderRadius.circular(25),
            child: Container(
              padding: EdgeInsets.symmetric(vertical: 12),
              alignment: Alignment.center,
              child: Text(
                "ducafecat",
                style: TextStyle(
                  fontSize: 22,
                ),
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

扩展方法:

  • animate: 为组件添加动画效果
  • align: 设置组件对齐方式
  • alignCenter: 居中对齐组件
  • alignLeft: 左对齐组件
  • alignRight: 右对齐组件
  • alignTop: 顶部对齐组件
  • alignBottom: 底部对齐组件
  • parent: 应用父组件
  • padding: 为组件添加内边距
  • paddingBottom: 添加底部内边距
  • paddingHorizontal: 添加水平内边距
  • paddingLeft: 添加左侧内边距
  • paddingRight: 添加右侧内边距
  • paddingTop: 添加顶部内边距
  • paddingVertical: 添加垂直内边距
  • paddingDirectional: 添加方向性内边距
  • sliverPadding: 为 Sliver 组件添加内边距
  • opacity: 设置组件透明度
  • offstage: 控制组件的可见性
  • neumorphism: 添加凹凸效果
  • boxShadow: 添加阴影效果
  • ripple: 添加涟漪效果
  • rotate: 旋转组件
  • scale: 缩放组件
  • translate: 平移组件
  • transform: 应用变换
  • overflow: 控制组件溢出行为
  • scrollable: 使组件可滚动
  • expanded: 在 Flex 容器中扩展组件
  • flexible: 在 Flex 容器中使组件灵活
  • positioned: 在 Stack 中定位组件
  • positionedDirectional: 在 Stack 中按方向定位组件
  • inkWell: 添加墨水效果和点击事件
  • safeArea: 将组件放置在安全区域
  • semanticsLabel: 添加语义标签
  • gestures: 添加手势识别
  • center: 居中组件
  • fittedBox: 使组件适应父组件
  • fractionallySizedBox: 根据父组件比例设置大小
  • card: 将组件包装在卡片中
  • limitedBox: 限制组件的最大大小
  • material: 将组件包装在 Material 中
  • mouseRegion: 添加鼠标交互区域

3 主题样式

快速写一个依据当前主题的主按钮。

主按钮

通过 context.colors.scheme 方式读取样式配置。

  Widget _buildView() {
    var scheme = context.colors.scheme;

    return Text("ducafecat")
        .fontSize(22)
        .fontWeight(FontWeight.bold)
        .textStyle(TextStyle(color: scheme.onPrimary))
        .alignment(Alignment.center)
        .borderRadius(all: 15)
        .ripple()
        .backgroundColor(scheme.primary, animate: true)
        .clipRRect(all: 25) // clip ripple
        .borderRadius(all: 25, animate: true)
        .elevation(
          pressed ? 0 : 1,
          borderRadius: BorderRadius.circular(25),
          shadowColor: Color(0x30000000),
        ) // shadow borderRadius
        .padding(vertical: 12) // margin
        .onTap(
          () => print('onTap'),
        )
        .scale(all: pressed ? 0.95 : 1.0, animate: true)
        .animate(Duration(milliseconds: 150), Curves.easeOut)
        .tight(
          height: 80,
          width: 200,
        )
        .center();
  }

扩展:

  • primary: 主要颜色
  • primaryLight: 主要颜色的亮色版本
  • primaryDark: 主要颜色的暗色版本
  • canvas: 画布颜色
  • scaffoldBackground: 脚手架背景色
  • card: 卡片颜色
  • divider: 分割线颜色
  • focus: 焦点颜色
  • hover: 悬停颜色
  • highlight: 高亮颜色
  • splash: 水波纹颜色
  • unselectedWidget: 未选中部件的颜色
  • disabled: 禁用状态颜色
  • secondaryHeader: 次要标题颜色
  • dialogBackground: 对话框背景色
  • indicator: 指示器颜色
  • hint: 提示文字颜色
  • scheme: 完整的颜色方案
  • shadow: 阴影颜色

4 工具类

4.1 屏幕尺寸信息

示例:

context.screenWidth

扩展:

  • screenWidth: 获取屏幕宽度
  • screenHeight: 获取屏幕高度
  • bottomBarHeight: 获取底部导航栏高度
  • statusBarHeight: 获取状态栏高度
  • textScaleFactor: 获取文本缩放因子
  • scaleWidth: 获取宽度的缩放因子
  • scaleHeight: 获取高度的缩放因子

4.2 时间差

示例:

// 创建一个 5 秒的 Duration
Duration fiveSeconds = 5.seconds;

扩展:

  • microseconds: 将数字转换为微秒的 Duration
  • milliseconds: 将数字转换为毫秒的 Duration
  • seconds: 将数字转换为秒的 Duration
  • minutes: 将数字转换为分钟的 Duration
  • hours: 将数字转换为小时的 Duration
  • days: 将数字转换为天的 Duration
  • months: 将数字转换为月的 Duration(假设一个月为 30 天)
  • quarters: 将数字转换为季度的 Duration(假设一个季度为 90 天)
  • quadrimesters: 将数字转换为四个月的 Duration(假设四个月为 120 天)
  • years: 将数字转换为年的 Duration(假设一年为 365 天)
  • future: 启动一个延迟 delayed

4.3 Icon 扩展

// 创建一个原始图标
Icon originalIcon = Icon(Icons.star, size: 24, color: Colors.yellow);

// 使用 copyWith() 创建一个新图标,修改大小和颜色
Icon newIcon = originalIcon.copyWith(size: 32, color: Colors.red);

// 仅修改图标大小
Icon largerIcon = originalIcon.iconSize(48);

// 仅修改图标颜色
Icon blueIcon = originalIcon.iconColor(Colors.blue);

4.4 List 集合

示例:

List<Widget> widgets = [Widget1(), Widget2(), Widget3()];
Widget column = widgets.toColumn(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
  separator: Divider(),
);

扩展:

  • toColumn(): 将 Widget 列表转换为 Column
  • toColumnSpace(): 将 Widget 列表转换为带有间距的 Column
  • toRow(): 将 Widget 列表转换为 Row
  • toRowSpace(): 将 Widget 列表转换为带有间距的 Row
  • toStack(): 将 Widget 列表转换为 Stack
  • toListView(): 将 Widget 列表转换为 ListView
  • toWrap(): 将 Widget 列表转换为 Wrap

4.5 媒体查询

示例:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 获取屏幕宽度
    double screenWidth = context.sizes.width;

    // 获取屏幕高度
    double screenHeight = context.sizes.height;

    // 获取屏幕边距
    EdgeInsets padding = context.sizes.padding;

    // 获取设备像素比
    double pixelRatio = context.sizes.devicePixelRatio;

    // 使用可能为空的属性
    double? maybeWidth = context.sizes.maybeWidth;

    return Container(
      width: screenWidth * 0.8,
      height: screenHeight * 0.5,
      padding: padding,
      child: Text(
        'Device Pixel Ratio: $pixelRatio',
        style: TextStyle(fontSize: 16 * context.sizes.textScaler.scale(1.0)),
      ),
    );
  }
}

扩展:

  • width: 屏幕宽度
  • height: 屏幕高度
  • padding: 屏幕边距
  • viewInsets: 视图插入
  • systemGestureInsets: 系统手势插入
  • viewPadding: 视图边距
  • devicePixelRatio: 设备像素比
  • textScaler: 文本缩放器

4.6 导航扩展

示例:

context.navigator.pushMaterial(NewPage());

扩展:

  • canPop: 检查是否可以弹出当前路由
  • maybePop: 尝试弹出当前路由
  • pop: 弹出当前路由
  • popUntil: 弹出路由直到满足条件
  • push: 推送新路由
  • pushMaterial: 使用 MaterialPageRoute 推送新页面
  • pushCupertino: 使用 CupertinoPageRoute 推送新页面
  • popAndPushNamed: 弹出当前路由并推送命名路由
  • pushAndRemoveUntil: 推送新路由并删除之前的路由直到满足条件
  • pushNamed: 推送命名路由
  • pushNamedAndRemoveUntil: 推送命名路由并删除之前的路由直到满足条件
  • pushReplacement: 推送新路由并替换当前路由
  • pushReplacementMaterial: 使用 MaterialPageRoute 推送新页面并替换当前路由
  • pushReplacementCupertino: 使用 CupertinoPageRoute 推送新页面并替换当前路由
  • pushReplacementNamed: 推送命名路由并替换当前路由
  • removeRoute: 移除指定路由
  • removeRouteBelow: 移除指定路由下方的路由
  • replace: 替换指定路由
  • replaceRouteBelow: 替换指定路由下方的路由

4.7 数字转内边距

示例:

// 创建所有方向上偏移量为 16 的内边距
EdgeInsets padding1 = 16.paddingAll();

// 创建水平方向上偏移量为 20 的内边距
EdgeInsets padding2 = 20.paddingHorizontal();

// 创建垂直方向上偏移量为 10 的内边距
EdgeInsets padding3 = 10.paddingVertical();

// 创建只有顶部偏移量为 8 的内边距
EdgeInsets padding4 = 8.paddingTop();

// 创建只有左侧偏移量为 12 的内边距
EdgeInsets padding5 = 12.paddingLeft();

// 创建只有右侧偏移量为 15 的内边距
EdgeInsets padding6 = 15.paddingRight();

// 创建只有底部偏移量为 5 的内边距
EdgeInsets padding7 = 5.paddingBottom();

扩展:

  • paddingAll: 创建所有方向上偏移量相等的内边距
  • paddingHorizontal: 创建水平方向上对称的内边距
  • paddingVertical: 创建垂直方向上对称的内边距
  • paddingTop: 创建只有顶部内边距的 EdgeInsets
  • paddingLeft: 创建只有左侧内边距的 EdgeInsets
  • paddingRight: 创建只有右侧内边距的 EdgeInsets
  • paddingBottom: 创建只有底部内边距的 EdgeInsets

4.8 平台查询

示例:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    if (context.isAndroid) {
      return Text('This is an Android device');
    } else if (context.isIOS) {
      return Text('This is an iOS device');
    } else if (context.isMacOS) {
      return Text('This is a MacOS device');
    } else if (context.isWindows) {
      return Text('This is a Windows device');
    } else if (context.isLinux) {
      return Text('This is a Linux device');
    } else if (context.isFuchsia) {
      return Text('This is a Fuchsia device');
    } else {
      return Text('Unknown platform');
    }
  }
}

扩展:

  • platform: 获取当前平台
  • isAndroid: 检查当前系统是否为 Android
  • isIOS: 检查当前系统是否为 iOS
  • isMacOS: 检查当前系统是否为 MacOS
  • isWindows: 检查当前系统是否为 Windows
  • isFuchsia: 检查当前系统是否为 Fuchsia
  • isLinux: 检查当前系统是否为 Linux

4.9 数字转 SizedBox

示例:

// 创建一个宽度为 10 的水平间距
SizedBox horizontalGap = 10.horizontalSpace;

// 创建一个高度为 20 的垂直间距
SizedBox verticalGap = 20.verticalSpace;

// 在 Widget 树中使用
Column(
  children: [
    Text('First item'),
    10.verticalSpace,  // 添加 10 单位的垂直间距
    Text('Second item'),
    20.verticalSpace,  // 添加 20 单位的垂直间距
    Text('Third item'),
  ],
);

Row(
  children: [
    Text('Left'),
    15.horizontalSpace,  // 添加 15 单位的水平间距
    Text('Right'),
  ],
);

扩展:

  • horizontalSpace: 创建具有指定宽度的 SizedBox
  • verticalSpace: 创建具有指定高度的 SizedBox

4.10 字符串

示例:

// 大写转换
print('hello world'.capitalize()); // 输出: Hello World
print('hello world'.capitalizeFirst()); // 输出: Hello world

// 布尔值转换
print('true'.isBool()); // 输出: true
print('false'.toBool()); // 输出: false

// 数字转换
print('123'.isNum()); // 输出: true
print('3.14'.toDouble()); // 输出: 3.14
print('42'.toInt()); // 输出: 42

// 颜色转换
Color color = 'FF5733'.toColor;
MaterialColor materialColor = 'FF5733'.toMaterialColor;

// 字符串处理
print('Hello  World'.removeAllWhitespace()); // 输出: HelloWorld
print('abc123'.hasMatch(r'\d+')); // 输出: true
print('<p>Hello</p>'.clearHtml); // 输出: Hello

扩展:

  • capitalize: 将每个单词的首字母大写
  • capitalizeFirst: 将字符串的第一个字母大写
  • isBool: 检查字符串是否可以转换为布尔值
  • toBool: 将字符串转换为布尔值
  • isNum: 检查字符串是否可以转换为数字
  • toNum: 将字符串转换为数字
  • isDouble: 检查字符串是否可以转换为双精度浮点数
  • toDouble: 将字符串转换为双精度浮点数
  • isInt: 检查字符串是否可以转换为整数
  • toInt: 将字符串转换为整数
  • toColor: 将十六进制颜色字符串转换为 Color 对象
  • toMaterialColor: 将十六进制颜色字符串转换为 MaterialColor 对象
  • removeAllWhitespace: 移除字符串中的所有空格
  • hasMatch: 检查字符串是否匹配指定的正则表达式模式
  • clearHtml: 移除字符串中的所有 HTML 标签

4.11 Text 文本

示例:

Text myText = Text('Hello, World!');

// 修改文本样式
myText = myText.textStyle(TextStyle(color: Colors.blue));

// 设置文本为粗体
myText = myText.bold();

// 设置文本为斜体
myText = myText.italic();

// 设置字体大小
myText = myText.fontSize(18);

// 设置字体系列
myText = myText.fontFamily('Roboto');

// 添加文本阴影
myText = myText.textShadow(color: Colors.grey, blurRadius: 2);

// 设置文本颜色
myText = myText.textColor(Colors.red);

// 设置文本对齐方式
myText = myText.textAlignment(TextAlign.center);

// 组合多个样式
myText = myText
    .bold()
    .fontSize(20)
    .textColor(Colors.green)
    .textAlignment(TextAlign.right);

扩展:

  • copyWith: 创建一个新的 Text 对象,可选择性地修改其属性
  • textStyle: 应用新的 TextStyle
  • textScale: 设置文本缩放因子
  • bold: 将文本设置为粗体
  • italic: 将文本设置为斜体
  • fontWeight: 设置文本的字体粗细
  • fontSize: 设置文本的字体大小
  • fontFamily: 设置文本的字体系列
  • letterSpacing: 设置文本的字母间距
  • wordSpacing: 设置文本的单词间距
  • textShadow: 为文本添加阴影效果
  • textElevation: 为文本添加立体效果
  • textColor: 设置文本颜色
  • textAlignment: 设置文本对齐方式
  • textDirection: 设置文本方向
  • textBaseline: 设置文本基线
  • textWidthBasis: 设置文本宽度基准

4.12 TextSpan 文本

示例:

TextSpan myTextSpan = TextSpan(text: 'Hello, World!');

// 修改文本样式
myTextSpan = myTextSpan.textStyle(TextStyle(color: Colors.blue));

// 设置文本为粗体
myTextSpan = myTextSpan.bold();

// 设置文本为斜体
myTextSpan = myTextSpan.italic();

// 设置字体大小
myTextSpan = myTextSpan.fontSize(18);

// 设置字体系列
myTextSpan = myTextSpan.fontFamily('Roboto');

// 添加文本阴影
myTextSpan = myTextSpan.textShadow(color: Colors.grey, blurRadius: 2);

// 设置文本颜色
myTextSpan = myTextSpan.textColor(Colors.red);

// 组合多个样式
myTextSpan = myTextSpan
    .bold()
    .fontSize(20)
    .textColor(Colors.green);

扩展:

  • copyWith: 创建一个新的 TextSpan 对象,可选择性地修改其属性
  • textStyle: 应用新的 TextStyle
  • bold: 将文本设置为粗体
  • italic: 将文本设置为斜体
  • fontWeight: 设置文本的字体粗细
  • fontSize: 设置文本的字体大小
  • fontFamily: 设置文本的字体系列
  • letterSpacing: 设置文本的字母间距
  • wordSpacing: 设置文本的单词间距
  • textShadow: 为文本添加阴影效果
  • textElevation: 为文本添加立体效果
  • textColor: 设置文本颜色
  • textBaseline: 设置文本基线

代码

https://github.com/ducafecat/flutter_package_ducafe_ui_core

小结

本文详细介绍了 Flutter 组件库 ducafe_ui_core 的功能与优势,重点强调了设计稿适配、视图层打薄和多种工具类的应用。通过使用 ducafe_ui_core,开发者能够有效提升开发效率,简化 Flutter 应用的设计与开发过程。该组件库旨在为开发者提供全面的支持,让他们在构建高质量移动应用时更加得心应手。希望本文能为您在 Flutter 开发中提供实用的参考和指导。

感谢阅读本文

如果有什么建议,请在评论中让我知道。我很乐意改进。


猫哥 APP

flutter 学习路径


© 猫哥 ducafecat.com

end