Flutter通用组件插件tch_common_widgets的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter通用组件插件tch_common_widgets的使用

tch_common_widgets 是一个用于Flutter项目的通用组件包。它包含了许多在多个项目中被复用的自定义组件,同时也支持全局主题定制。该包由 Tomas Chyly 开发,并且在一些功能上依赖于另一个包 tch_appliable_core

平台注意事项

虽然我在多个平台上使用过Flutter,但我的主要关注点是在移动设备和桌面应用上。因此,某些组件和特性可能不适用于Web平台,但应该可以在其他平台上正常工作。我个人认为Flutter目前还不完全适合Web开发。

开发注意事项

由于时间限制,文档可能有些过时,但是该包本身会继续得到维护和发展。

目录

  1. 安装
  2. 主题
  3. 组件
  4. 对话框
  5. 路线图

安装

在你的项目的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  tch_common_widgets: ^0.37.1+1

如果IDE没有自动导入,可以手动添加:

import 'package:tch_common_widgets/tch_common_widgets.dart';

主题

CommonTheme 的设置与使用

首先,在 lib/core/AppTheme.dart 文件中创建颜色常量、文本样式和尺寸常量,然后使用它们来创建兼容 CommonTheme 的样式。以下是示例代码:

const kColorPrimary = const Color(0xFF1a1a1a);
const kColorPrimaryLight = const Color(0xFF404040);
const kColorPrimaryDark = const Color(0xFF000000);
const kColorSecondary = kColorGold;
const kColorSecondaryLight = kColorGoldLight;
const kColorSecondaryDark = kColorGoldDarker;

const kColorTextPrimary = kColorSilver;

const kFontFamily = 'Custom Font Family Name';

const kText = const TextStyle(color: kColorTextPrimary, fontSize: 16);
const kTextHeadline = const TextStyle(color: kColorTextPrimary, fontSize: 20);

/// 构建方法,提供给CoreApp或MaterialApp,它将所有页面包裹在CommonTheme中
/// 自定义CommonTheme以适应应用需求
Widget appThemeBuilder(BuildContext context, Widget child) {
  /// 根据操作系统更改圆角半径
  BorderRadius platformBorderRadius = const BorderRadius.all(const Radius.circular(8));
  if (!kIsWeb && (Platform.isWindows || Platform.isLinux)) {
    platformBorderRadius = BorderRadius.circular(0);
  }

  /// 默认为IconButtonWidgets设置样式,使其更适合桌面使用
  final kIconButtonStyle = IconButtonStyle(
    width: kMinInteractiveSizeNotTouch + kCommonHorizontalMarginHalf,
    height: kMinInteractiveSizeNotTouch + kCommonVerticalMarginHalf,
    iconWidth: kIconSizeNotTouch,
    iconHeight: kIconSizeNotTouch,
    color: kColorTextPrimary,
    borderRadius: platformBorderRadius,
  );

  /// AppBar中的IconButtonWidgets具有不同的默认样式
  const kAppBarIconButtonStyle = const IconButtonStyle(
    variant: IconButtonVariant.IconOnly,
    color: kColorTextPrimary,
    borderRadius: platformBorderRadius,
  );

  final OutlineInputBorder platformInputBorder = OutlineInputBorder(
    borderSide: const BorderSide(
      width: 1,
    ),
    borderRadius: platformBorderRadius,
  );

  /// 所有TextFormFieldWidgets的默认样式
  final kTextFormFieldStyle = TextFormFieldStyle(
    inputDecoration: TextFormFieldStyle().inputDecoration.copyWith(
          enabledBorder: platformInputBorder,
          disabledBorder: platformInputBorder,
          focusedBorder: platformInputBorder,
          errorBorder: platformInputBorder,
          focusedErrorBorder: platformInputBorder,
        ),
    borderColor: kColorGold,
    fillColorDisabled: kColorSilver,
    disabledBorderColor: kColorSilverDarker,
    errorColor: kColorRed,
  );

  /// 修改默认样式以获取电子邮件字段的样式
  final TextFormFieldStyle kEmailTextFormFieldStyle = kTextFormFieldStyle.copyWith(
    textCapitalization: TextCapitalization.none,
    keyboardType: TextInputType.emailAddress,
    validations: [
      FormFieldValidation(
        validator: validateEmail,
        errorText: '请输入有效的电子邮件地址', // 或者使用tt('form.email.error'),如果你使用的是CoreApp Translator
      ),
    ],
  );

  return AppTheme(
    child: child,
    fontFamily: prefsInt(PREFS_FANCY_FONT) == 1 ? kFontFamily : null,
    buttonsStyle: ButtonsStyle(
      iconButtonStyle: kIconButtonStyle,
    ),
    appBarIconButtonStyle: kAppBarIconButtonStyle,
    formStyle: FormStyle(
      textFormFieldStyle: kTextFormFieldStyle,
    ),
    emailTextFormFieldStyle: kEmailTextFormFieldStyle,
  );
}

/// 自定义AppTheme扩展CommonTheme以允许自定义样式
class AppTheme extends CommonTheme {
  final IconButtonStyle appBarIconButtonStyle;
  final TextFormFieldStyle emailTextFormFieldStyle;

  /// AppTheme初始化
  AppTheme({
    required Widget child,
    String? fontFamily,
    required ButtonsStyle buttonsStyle,
    required this.appBarIconButtonStyle,
    required DialogsStyle dialogsStyle,
    required FormStyle formStyle,
    required this.emailTextFormFieldStyle,
  }) : super(
          /// 子节点需要是CommonTheme,否则通用组件将无法正常工作
          child: CommonTheme(
            child: child,
            fontFamily: fontFamily,
            buttonsStyle: buttonsStyle,
            dialogsStyle: dialogsStyle,
            formStyle: formStyle,
          ),
          fontFamily: fontFamily,
          buttonsStyle: buttonsStyle,
          dialogsStyle: dialogsStyle,
          formStyle: formStyle,
        );
}

要使用你定义的非默认样式,只需将它们传递给相应的组件即可。例如:

...
final appTheme = CommonTheme.of<AppTheme>(context)!;
...
/// 使用kAppBarIconButtonStyle样式为AppBar中的IconButtonWidgets
IconButtonWidget(
  style: appTheme.appBarIconButtonStyle,
  svgAssetPath: 'images/back.svg',
  onTap: () {
    Navigator.pop(context);
  },
);
...
...
final appTheme = CommonTheme.of<AppTheme>(context)!;
...
/// kEmailTextFormFieldStyle 确保此字段看起来和行为都像电子邮件字段
TextFormFieldWidget(
  style: appTheme.emailTextFormFieldStyle,
  controller: _emailController,
  focusNode: _emailFocus,
  nextFocus: _subjectFocus,
  label: 'Email',
  textInputAction: TextInputAction.next,
),
...

如果想在任何地方访问 CommonTheme 并在某些组件中临时修改样式:

final commonTheme = CommonTheme.of(context)!;
...
/// 多行文本字段,临时修改默认样式以实现句子首字母大写
TextFormFieldWidget(
  style: commonTheme.formStyle.textFormFieldStyle.copyWith(
    textCapitalization: TextCapitalization.sentences,
  ),
  controller: _messageController,
  focusNode: _messageFocus,
  label: tt('feedback.screen.message'),
  lines: 3,
  validations: [
    FormFieldValidation(
      validator: validateRequired,
      errorText: tt('feedback.screen.message.error'),
    ),
  ],
),
...
在整个应用中应用你的CommonTheme
...
@override
Widget build(BuildContext context) {
  return CoreApp( // 如果你不使用我的Core包,则使用MaterialApp
    ...
    builder: appThemeBuilder,
    theme: ThemeData( /// 你可以将CommonTheme与Material主题结合起来
      backgroundColor: kColorPrimaryLight,
      primaryColor: kColorPrimary,
      primaryColorLight: kColorPrimaryLight,
      primaryColorDark: kColorPrimaryDark,
      accentColor: kColorSecondary,
      splashColor: kColorSecondary,
      shadowColor: kColorShadow,
    ),
    ...
  );
}
...

组件

CommonSpaces
  • CommonTheme 兼容,也可以单独使用。

这些是一组用于轻松和标准地在其他组件之间插入间距的组件。

PreferencesSwitchWidget
  • CommonTheme 兼容,也可以单独使用。
  • 需要 tch_appliable_core 包来处理偏好设置。

简单的设置切换/开关,从偏好设置中获取并切换整数,将其作为布尔值使用。

SwitchToggleWidget
  • CommonTheme 兼容,也可以单独使用。

Switch的替代组件,包装了 IconButtonWidget 和样式。

TextFormFieldWidget
  • CommonTheme 兼容,也可以单独使用。
  • 自定义解决方案,修复了Flutter iOS版本的自动更正问题!
  • 该解决方案自Flutter >= 3.16.0后不再必要。

封装了 TextFormField 以进行额外的样式调整和功能,主要与 CommonTheme 一起使用。有两种变体:Material和Cupertino风格。

如果你在 CommonTheme 中设置或直接传递给组件:

TextFormFieldStyle(
  ...
  iOSUseNativeTextField: true,
  ...
)

更多关于Flutter通用组件插件tch_common_widgets的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter通用组件插件tch_common_widgets的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用tch_common_widgets插件的一个简单示例。tch_common_widgets是一个假设的通用组件插件,因此具体API可能会有所不同,但我会根据常见的Flutter插件使用模式给出一个示例。

首先,你需要确保你的Flutter项目中已经添加了tch_common_widgets插件。你可以通过修改pubspec.yaml文件来添加依赖:

dependencies:
  flutter:
    sdk: flutter
  tch_common_widgets: ^x.y.z  # 替换为实际的版本号

然后运行flutter pub get来安装依赖。

假设tch_common_widgets插件提供了一些常用的组件,比如一个自定义的按钮(CustomButton)和一个自定义的加载指示器(CustomLoadingIndicator)。以下是如何在你的Flutter应用中使用这些组件的代码示例:

import 'package:flutter/material.dart';
import 'package:tch_common_widgets/tch_common_widgets.dart';  // 导入插件

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isLoading = false;

  void handleButtonClick() {
    setState(() {
      isLoading = true;
      // 模拟加载过程
      Future.delayed(Duration(seconds: 2), () {
        setState(() {
          isLoading = false;
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('tch_common_widgets Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // 使用自定义按钮组件
            CustomButton(
              text: 'Click Me',
              onPressed: handleButtonClick,
            ),
            SizedBox(height: 20),
            // 根据加载状态显示不同的组件
            if (isLoading)
              CustomLoadingIndicator()  // 显示加载指示器
            else
              Text('Loading complete!'),  // 加载完成后显示文本
          ],
        ),
      ),
    );
  }
}

在这个示例中:

  1. CustomButton 是一个假设的自定义按钮组件,它接受一个文本标签和一个点击事件回调。
  2. CustomLoadingIndicator 是一个假设的自定义加载指示器组件。
  3. _MyHomePageState中,我们有一个布尔变量isLoading来控制加载状态。点击按钮时,我们设置isLoadingtrue,模拟一个加载过程,2秒后将其设置回false
  4. 根据isLoading的值,我们在UI中显示不同的组件:加载中时显示CustomLoadingIndicator,加载完成后显示文本。

请注意,由于tch_common_widgets是一个假设的插件,上述代码中的CustomButtonCustomLoadingIndicator组件及其API可能并不真实存在。你需要根据实际的tch_common_widgets插件文档来调整代码。通常,插件的README文件或官方文档会提供详细的组件使用说明和示例代码。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!