美文网首页
Flutter 之 组合实例 GradientButton(七十

Flutter 之 组合实例 GradientButton(七十

作者: maskerII | 来源:发表于2022-05-24 18:43 被阅读0次

    在Flutter中页面UI通常都是由一些低级别组件组合而成,当我们需要封装一些通用组件时,应该首先考虑是否可以通过组合其它组件来实现,如果可以,则应优先使用组合,因为直接通过现有组件拼装会非常简单、灵活、高效。

    image.png

    1. 实例:自定义渐变按钮

    1. 实现GradientButton

    Flutter Material组件库中的按钮默认不支持渐变背景,为了实现渐变背景按钮,我们自定义一个GradientButton组件,它需要支持一下功能:

    • 背景支持渐变色
    • 手指按下时有涟漪效果
    • 可以支持圆角

    DecoratedBox可以支持背景色渐变和圆角,InkWell在手指按下有涟漪效果,所以我们可以通过组合DecoratedBox和InkWell来实现GradientButton

    
    class GradientButton extends StatelessWidget {
      const GradientButton({
        Key? key,
        this.colors,
        this.width,
        this.height,
        this.borderRadius,
        required this.tapCallback,
        required this.child,
        this.disable = false,
      }) : super(key: key);
    
      final List<Color>? colors; // 渐变色数组
      final double? width; // 按钮 宽
      final double? height; // 按钮 高
      final BorderRadius? borderRadius; // 按钮 圆角
    
      final GestureTapCallback tapCallback;
      final bool disable; // 禁用
    
      final Widget child; // 子组件
    
      @override
      Widget build(BuildContext context) {
        ThemeData theme = Theme.of(context);
    
        List<Color> _colors = [];
        if (disable) {
          //确保colors数组不空
          _colors = [Colors.grey.withAlpha(100), Colors.grey.withAlpha(100)];
        } else {
          //确保colors数组不空
          _colors = colors ?? [theme.primaryColor, theme.primaryColorDark];
        }
    
        return DecoratedBox(
          decoration: BoxDecoration(
            borderRadius: borderRadius,
            gradient: LinearGradient(colors: _colors),
          ),
          child: Material(
            type: MaterialType.transparency, // 透明材质 用于绘制墨水飞溅和高光
            child: InkWell(
              onTap: disable ? null : tapCallback,
              splashColor: _colors.last,
              borderRadius: borderRadius,
              enableFeedback: !disable, // 是否给予操作反馈
              highlightColor: Colors.transparent,
              child: ConstrainedBox(
                constraints: BoxConstraints.tightFor(width: width, height: height),
                child: Center(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: DefaultTextStyle(
                      style: TextStyle(fontWeight: FontWeight.bold),
                      child: child,
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }
    
    

    可以看到GradientButton是由DecoratedBox、Padding、Center、InkWell等组件组合而成。更多功能可以根据实际需要来完善。

    2. 使用GradientButton

    
    class MSGradientButtonDemo extends StatelessWidget {
      const MSGradientButtonDemo({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text("GradientButton")),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                GradientButton(
                  tapCallback: () => print("Button Clicked 1"),
                  child: Text("Submit 1"),
                  colors: [Colors.orange, Colors.cyan],
                  height: 50,
                ),
                GradientButton(
                  tapCallback: () => print("Button Clicked 2"),
                  child: Text("Submit 2"),
                  colors: [Colors.cyan, Colors.green],
                  height: 50,
                ),
                GradientButton(
                  tapCallback: () => print("Button Clicked 3"),
                  child: Text("Submit 3"),
                  colors: [Colors.yellow, Colors.red, Colors.orange],
                  height: 50,
                ),
                GradientButton(
                  tapCallback: () => print("Button Clicked 4"),
                  child: Text("Submit 4"),
                  colors: [Colors.orange, Colors.cyan],
                  height: 50,
                  width: 200,
                  borderRadius: BorderRadius.circular(8),
                ),
                GradientButton(
                  tapCallback: () => print("Button Clicked 5"),
                  child: Text("enable 5"),
                  width: 200,
                  height: 50,
                  borderRadius: BorderRadius.circular(8),
                  colors: [Colors.grey, Colors.red],
                  disable: false,
                ),
                GradientButton(
                  tapCallback: () => print("Button Clicked 6"),
                  child: Text("Disable 6"),
                  width: 200,
                  height: 50,
                  borderRadius: BorderRadius.circular(8),
                  disable: true,
                )
              ],
            ),
          ),
        );
      }
    }
    
    111.gif

    2. 总结

    通过组合的方式定义组件和我们之前写界面并无差异,不过在抽离出单独的组件时我们要考虑代码规范性,如必要参数要用required关键词标注,对于可选参数在特定场景需要判空或设置默认值等。这是由于使用者大多时候可能不了解组件的内部细节,所以为了保证代码健壮性,我们需要在用户错误地使用组件时能够兼容或报错提示(使用assert断言函数)。

    相关文章

      网友评论

          本文标题:Flutter 之 组合实例 GradientButton(七十

          本文链接:https://www.haomeiwen.com/subject/uyfsprtx.html