飘动的自定义小部件样式

发布于 2025-01-25 18:38:28 字数 2579 浏览 6 评论 0原文

我正在与设计师紧密地研究一个大型应用程序。
我是样式指南和组件设计过程的一部分,
设计师交出了他的作品,现在轮到我将一些原型和样式转换为真正的Flutter应用程序了。

我很难将“样式指南”转换为颤动小部件。
例如,我有一个从头开始创建的自定义芯片小部件,具有许多样式属性。
该芯片有两种主要的不同样式(正常和突出显示),
广泛使用芯片(我相信有50多个参考文献),不包括使用它的其他更复杂的小部件。

我尝试:

  1. 为每个大型小部件创建一个样式类,并在主题上创建扩展名。
class MyCustomChip extends StatelessWidget {
    Widget build(BuildContext context) {
       final style = Theme.of(context).myCustomChip;
       /** return the custom chip **/
    }
}

class MyCustomChipStyle {
/** many style properties **/
}

extension MyCustomChipThemeData on ThemeData {
    MyCustomChipStyle get myCustomChip => ...
}

  1. 创建一个静态样式类,并在小部件使用时传递相关样式属性。
class MyCustomChip extends StatelessWidget {
    final Color color;
    final BorderRadius borderRadius;
    /** many more styling properties **/
}

abstract class MyCustomChipValues {
    static const BorderRadius kBorder = /** Getting value from a predefined radiuses **/
    static const Color kColor = /** Getting value from a predefined palette **/
    /** Many more **/
}

class WidgetUsingTheChip extends StatelessWidget {
    Widget build(BuildContext context) {
      /** those lines will be duplicated alot **/
      return MyCustomChip(
        color: MyCustomChipValues.kColor,
        borderRadius: MyCustomChipValues.kBorder,
        /** Many more **/
      );
    }
}
  1. 使用自定义小部件内的所有相关样式属性,并且没有揭露它们。
abstract class MyCustomChipValues {
    static const BorderRadius kBorder = /** Getting value from a predefined radiuses **/
    static const Color kColor = /** Getting value from a predefined palette **/
    /** Many more **/
}

class MyCustomChip extends StatelessWidget {
    Widget build(BuildContext context) {
       /** making it virtually impossible to change style depending on state **/
       return Container(
          color: MyCustomChipValues.kColor,
          /** Many more **/
       );
    }
}

class WidgetUsingTheChip extends StatelessWidget {
    Widget build(BuildContext context) {
      return MyCustomChip();
    }
}

我已经定义了其他样式类:

  • 插图(各种填充和边距)
  • 颜色(我们的调色板,按钮,芯片,输入,脚手架等)
  • Borderradiuses
  • Shadows
  • Animations(持续时间和曲线)
  • 指南(基于天沟和设计网格网格我们对
  • 其他课程进行了原型的原型...

在需要时我无法将以下哪项更容易维护和重构。.

关于如何管理整个样式指南的任何建议 -代码将有所帮助,
特别是如何管理自定义小部件样式。

谢谢 !

I'm working on a big app tightly with the designer.
I was a part of the style guide and the component design process,
the designer handed off his work and now its my turn to translate some prototypes and styles to real flutter app.

I'm having a really hard time translating the style guide to flutter widgets.
For example, I have a custom chip widget created from scratch, with many style properties.
There are two main different styles for this chip (normal and highlighted),
and the chip is used widely (I believe more than 50 references), excluding other more complex widgets using it.

I tried :

  1. Creating a style class for each big widget, and created extension on ThemeData.
class MyCustomChip extends StatelessWidget {
    Widget build(BuildContext context) {
       final style = Theme.of(context).myCustomChip;
       /** return the custom chip **/
    }
}

class MyCustomChipStyle {
/** many style properties **/
}

extension MyCustomChipThemeData on ThemeData {
    MyCustomChipStyle get myCustomChip => ...
}

  1. Created a static style class, and passed relevant style properties every time the widget used.
class MyCustomChip extends StatelessWidget {
    final Color color;
    final BorderRadius borderRadius;
    /** many more styling properties **/
}

abstract class MyCustomChipValues {
    static const BorderRadius kBorder = /** Getting value from a predefined radiuses **/
    static const Color kColor = /** Getting value from a predefined palette **/
    /** Many more **/
}

class WidgetUsingTheChip extends StatelessWidget {
    Widget build(BuildContext context) {
      /** those lines will be duplicated alot **/
      return MyCustomChip(
        color: MyCustomChipValues.kColor,
        borderRadius: MyCustomChipValues.kBorder,
        /** Many more **/
      );
    }
}
  1. Used all the relevant style properties inside the custom widget, and didn't expose them.
abstract class MyCustomChipValues {
    static const BorderRadius kBorder = /** Getting value from a predefined radiuses **/
    static const Color kColor = /** Getting value from a predefined palette **/
    /** Many more **/
}

class MyCustomChip extends StatelessWidget {
    Widget build(BuildContext context) {
       /** making it virtually impossible to change style depending on state **/
       return Container(
          color: MyCustomChipValues.kColor,
          /** Many more **/
       );
    }
}

class WidgetUsingTheChip extends StatelessWidget {
    Widget build(BuildContext context) {
      return MyCustomChip();
    }
}

I have defined other style classes :

  • Insets (various paddings and margins)
  • Colors (our palette, with buttons, chips, input, scaffold, etc..)
  • BorderRadiuses
  • Shadows
  • Animations (duration and curve)
  • Guidelines (based on the gutter and the design grid we prototyped with)
  • Other classes...

I cant wrap my head on which of the following is more easy to maintain and refactor in the time of need..

Any suggestion on how to manage this whole Style guide -> code will be helpful,
especially on how to manage custom widget styles.

Thanks !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

活泼老夫 2025-02-01 18:38:28

基本上,您需要了解自定义小部件的概念,并了解存在的不同类型的芯片。

  1. 您可以有几种类型的子弹 - 选择,过滤器,动作,输入 - 芯片。 芯片 - 材料设计

  2. 来自材料设计提供的不同类型的样式,您将其调整到您从设计团队中收到的小部件。例如,将子弹包裹在一列中以带有额外的标签。

class MyActionChip extends StatelessWidget {
  /// Default chip have a string label
  const MyActionChip({
    required this.label,
    required this.onPressed,
    Key? key,
    this.onTapAvatar,
  })  : child = null, super(key: key);
  
  /// Default chip have a widget label
  const MyActionChip.child({
    required this.child,
    required this.onPressed,
    Key? key,
    this.onTapAvatar,
  })  : label = null, super(key: key);
  
  final String? label;
  final Widget? child;
  final VoidCallback? onTapAvatar;
  final Function()? onPressed;
  
  @override
  Widget build(BuildContext context) {
    return InputChip(
      backgroundColor: MyColors.milk,
      shape: const RoundedRectangleBorder(
          borderRadius:
          BorderRadius.all(Radius.circular(MyConstants.borderRadiusMedium)),
          side: BorderSide(color: MyColors.anthracite20),
      ),
      avatar: const Icon(
          MyIcons.plus,
          size: 18,
          color: MyColors.anthracite,
      ),
      labelPadding:
          const EdgeInsets.only(right: SdConstants.contentPaddingMedium),
          label: child ??
              Text(
                  label!,
                  style: const TextStyle(
                    color: MyColors.anthracite,
            fontSize: 14,
            fontWeight: FontWeight.bold,
          ),
        ),
      onPressed: onPressed,
    );
  }
}
  1. 在复杂的情况下,您可以根据复杂性构建自定义芯片。

注意:根据屏幕和回调而变化的参数仅在构造函数之外暴露。您需要几个构造函数/类来自定义所有芯片。

Basically you need to understand the concept of custom widgets and know the different types of chips that exist.

  1. You can have several types of bullets - choice, filter, action, input - Chips. Chips - Material Design

  2. From the different types of styles that material design offers, you adapt this to the widgets you receive from your design team. For example wrap your bullets in a Column to have an extra Label.

class MyActionChip extends StatelessWidget {
  /// Default chip have a string label
  const MyActionChip({
    required this.label,
    required this.onPressed,
    Key? key,
    this.onTapAvatar,
  })  : child = null, super(key: key);
  
  /// Default chip have a widget label
  const MyActionChip.child({
    required this.child,
    required this.onPressed,
    Key? key,
    this.onTapAvatar,
  })  : label = null, super(key: key);
  
  final String? label;
  final Widget? child;
  final VoidCallback? onTapAvatar;
  final Function()? onPressed;
  
  @override
  Widget build(BuildContext context) {
    return InputChip(
      backgroundColor: MyColors.milk,
      shape: const RoundedRectangleBorder(
          borderRadius:
          BorderRadius.all(Radius.circular(MyConstants.borderRadiusMedium)),
          side: BorderSide(color: MyColors.anthracite20),
      ),
      avatar: const Icon(
          MyIcons.plus,
          size: 18,
          color: MyColors.anthracite,
      ),
      labelPadding:
          const EdgeInsets.only(right: SdConstants.contentPaddingMedium),
          label: child ??
              Text(
                  label!,
                  style: const TextStyle(
                    color: MyColors.anthracite,
            fontSize: 14,
            fontWeight: FontWeight.bold,
          ),
        ),
      onPressed: onPressed,
    );
  }
}
  1. In complex cases, you can build a custom chip according to the complexity.

Note: the parameters that vary according to the screens and callbacks are simply exposed outside the constructor. You need several constructors/classes to customize all your chips.

于我来说 2025-02-01 18:38:28

我建议使用sarenitedwidget,那么您不必依靠外部软件包。

例如:

class CustomStyle extends InheritedWidget {
  const CustomStyle({
    Key? key,
    required this.data,
    required Widget child,
  }) : super(key: key, child: child);

  final StyleData data;

  static CustomStyle of(BuildContext context) {
    final CustomStyle? result =
        context.dependOnInheritedWidgetOfExactType<CustomStyle>();
    assert(result != null, 'No CustomStyle found in context');
    return result!;
  }

  @override
  bool updateShouldNotify(CustomStyle oldWidget) => data != oldWidget.data;
}

您可以创建这些并以任何方式添加到customStyle,也许根据小部件具有多个类,或者通过颜色分开。

class StyleData {
  const StyleData({
    required this.color,
    required this.padding,
  });

  final Color color;
  final EdgeInsets padding;
}

CustomStyle将您的Interialapp包装,传递您的数据。

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomStyle(
      data: const StyleData(
        color: Colors.blue,
        padding: EdgeInsets.zero,
      ),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

然后,您可以在所有自定义小部件中访问样式:

class CustomContainer extends StatelessWidget {
  const CustomContainer({Key? key, this.color, this.padding}) : super(key: key);

  final Color? color;
  final EdgeInsets? padding;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color ?? CustomStyle.of(context).data.color,
      padding: padding ?? CustomStyle.of(context).data.padding,
      child: const Text('Hello'),
    );
  }
}

任何问题都让我知道。

I would recommend using InheritedWidget, then you don't have to rely on external packages.

For example:

class CustomStyle extends InheritedWidget {
  const CustomStyle({
    Key? key,
    required this.data,
    required Widget child,
  }) : super(key: key, child: child);

  final StyleData data;

  static CustomStyle of(BuildContext context) {
    final CustomStyle? result =
        context.dependOnInheritedWidgetOfExactType<CustomStyle>();
    assert(result != null, 'No CustomStyle found in context');
    return result!;
  }

  @override
  bool updateShouldNotify(CustomStyle oldWidget) => data != oldWidget.data;
}

You could create these and add to your CustomStyle in whatever way you want, maybe have multiple class depending on the widget, or separate them by colors.

class StyleData {
  const StyleData({
    required this.color,
    required this.padding,
  });

  final Color color;
  final EdgeInsets padding;
}

Wrap your MaterialApp with your CustomStyle, pass your data.

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomStyle(
      data: const StyleData(
        color: Colors.blue,
        padding: EdgeInsets.zero,
      ),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

Then you can access you styling in all your custom widgets:

class CustomContainer extends StatelessWidget {
  const CustomContainer({Key? key, this.color, this.padding}) : super(key: key);

  final Color? color;
  final EdgeInsets? padding;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color ?? CustomStyle.of(context).data.color,
      padding: padding ?? CustomStyle.of(context).data.padding,
      child: const Text('Hello'),
    );
  }
}

Any questions just let me know.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文