Flutter布局锦囊---涂鸦风格按钮

版权声明:本文为博主原创文章,未经博主允许不得转载。Flutter交流QQ群:271733776,共同学习、进步! https://blog.csdn.net/hekaiyou/article/details/85699043

设计给的效果如下:

UI布局图

拿到设计后,先把整体拆分成几个部分:

  1. “可点击框”,使用堆栈(Stack)组件布局的可点击区域。
  2. “底部矩形”,用来衬托“主要矩形”,以形成立体效果的矩形。
  3. “主要矩形”,按钮主体部分,通过调整上下位置来模拟按压效果。

然后就可以开始进行编码了。

第1步:绘制组件树

涂鸦风格按钮的组件树

第2步:实现“可点击框”

通过手势探测器(GestureDetector)组件,你可以通过检测多种手势并设置对应的处理函数。通过大小框(SizedBox)组件为“按钮”设置一个活动区域,并将堆栈(Stack)组件作为子组件置于其中。同时,通过activationonTapCallback两个变量来传递状态和回调函数。

import 'package:flutter/material.dart';

/// 自定义的涂鸦按钮组件。
class DoodleButton extends StatefulWidget {
  // TODO: 第3步:实现“底部矩形”,成员变量。
  // TODO: 第4步:实现“主要矩形”,成员变量。
  /// 按钮的激活状态,默认为`false`。
  final bool activation;
  /// 发生点击时的回调函数。
  final Function onTapCallback;

  DoodleButton({
    // TODO: 第3步:实现“底部矩形”,默认构造。
    // TODO: 第4步:实现“主要矩形”,默认构造。
    this.activation: false,
    this.onTapCallback,
  });

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

/// 与自定义的涂鸦按钮组件关联的状态子类。
class _DoodleButtonState extends State<DoodleButton> {
  // TODO: 第4步:实现“主要矩形”,控制按压。

  @override
  Widget build(BuildContext context) {
    // 手势探测器(`GestureDetector`)组件,检测手势的组件。
    // 尝试识别与其非空回调相对应的手势。如果此组件具有子项,
    // 则它会根据其大小调整行为推迟该子项。
    // 如果它没有子组件,它会变得适合父组件。
    return GestureDetector(
      // 在点击(`onTap`)属性,发生了点击。
      onTap: widget.activation ? () {
        setState(() {
          // TODO: 第4步:实现“主要矩形”,“按下”按钮。
          widget.onTapCallback();
          // TODO: 第4步:实现“主要矩形”,“松开”按钮。
        });
      } : null,
      child: SizedBox(
        height: 48.0,
        // 堆栈(`Stack`)组件,用于将其子级相对于其框的边缘定位。
        child: Stack(
          children: <Widget>[
            // TODO: 第3步:实现“底部矩形”,实现容器。
            // TODO: 第4步:实现“主要矩形”,实现容器。
          ]
        ),
      ),
    );
  }
}

第3步:实现“底部矩形”

通过backgroundColorsilentBackgroundColor变量来传递“按钮”可用、不可用时,“底部矩形”的颜色。

  // TODO: 第3步:实现“底部矩形”,成员变量。
  /// 按钮的底部颜色,默认为`#D95636`。
  final Color backgroundColor;
  /// 不可用按钮的底部颜色,默认为`#8A8A8A`。
  final Color silentBackgroundColor;

    // TODO: 第3步:实现“底部矩形”,默认构造。
    this.backgroundColor: const Color(0xFFD95636),
    this.silentBackgroundColor: const Color(0xFF8A8A8A),

使用对齐(Align)组件,并通过Alignment.bottomCenter将其设置为靠近下方对齐。再用边界半径(BorderRadius)类,将矩形的4个边角设置为圆角。

            // TODO: 第3步:实现“底部矩形”,实现容器。
            // 对齐(`Align`)组件,用于将其子项与其自身对齐,并根据子级的大小自行调整大小。
            Align(
              // 对准属性,如何调整子组件。
              alignment: Alignment.bottomCenter,
              child: Container(
                decoration: BoxDecoration(
                  color: widget.activation ? widget.backgroundColor : widget.silentBackgroundColor,
                  // 框装饰(`BoxDecoration`)类的边界(`border`)属性,在背景颜色、渐变或图像上方绘制的边框。
                  // 边界(`Border`)类,框的边框,由四个边组成:顶部、右侧、底部、左侧。
                  border: Border.all(
                    // 宽度参数,边框的宽度。
                    width: 2.0,
                    // 颜色参数,边框的颜色。
                    color: const Color(0xFF282828),
                  ),
                  // 边界半径(`borderRadius`)属性,如果为非空值,则此属性将对此框的角进行舍入。
                  // 边界半径(`BorderRadius`)类,矩形每个角的一组不可变半径。
                  // 边界半径.所有(`BorderRadius.all`)构造函数,创建一个边界半径,设置所有的半径。
                  borderRadius: BorderRadius.all(
                    // 半径(`Radius`)类,圆形或椭圆形的半径。
                    // 半径.圆(`Radius.circular`)构造函数,构造一个圆形半径,x和y将具有相同的半径值。
                    Radius.circular(2.0),
                  ),
                ),
                height: 42.0,
              ),
            ),

第4步:实现“主要矩形”

通过mainColorsilentMainColor变量来传递“按钮”可用、不可用时,“底部矩形”的颜色,promptText变量传递“按钮”的操作提示文本。

  // TODO: 第4步:实现“主要矩形”,成员变量。
  /// 按钮的操作提示文本。
  final String promptText;
  /// 按钮的主要颜色,默认为`#FF6B47`。
  final Color mainColor;
  /// 不可用按钮的主要颜色,默认为`#B2B2B2`。
  final Color silentMainColor;

    // TODO: 第4步:实现“主要矩形”,默认构造。
    this.promptText,
    this.mainColor: const Color(0xFFFF6B47),
    this.silentMainColor: const Color(0xFFB2B2B2),

通过对准(Alignment)类来控制“主要矩形”的按压效果:靠近上边时是松开按钮;靠近下边时是按下按钮。

  // TODO: 第4步:实现“主要矩形”,控制按压。
  // 对准(`Alignment`)类,矩形内的一个点。
  // [0.0,0.0]表示矩形的中心,[-1.0到+1.0]的距离是从矩形的一边到矩形的另一边的距离。
  // 因此,水平(或垂直)[2.0]单位等于矩形的宽度(或高度)。
  /// 主要容器的对齐方式,控制按钮的按压状态。
  Alignment mainContainerAlignment = Alignment.topCenter;

          // TODO: 第4步:实现“主要矩形”,“按下”按钮。
          mainContainerAlignment = Alignment.bottomCenter;
          widget.onTapCallback();
          // TODO: 第4步:实现“主要矩形”,“松开”按钮。
          mainContainerAlignment = Alignment.topCenter;

最后实现“主要矩形”的布局代码。

            // TODO: 第4步:实现“主要矩形”,实现容器。
            Align(
              alignment: mainContainerAlignment,
              child: Container(
                child: Center(
                  child: Text(
                    widget.promptText,
                    style: TextStyle(
                      color: const Color(0xFF282828),
                      fontSize: 18.0,
                      // 字体重量(`FontWeight`)类,用于绘制文本的字形的粗细。
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                decoration: BoxDecoration(
                  color: widget.activation ? widget.mainColor : widget.silentMainColor,
                  border: Border.all(
                    width: 2.0,
                    color: const Color(0xFF282828),
                  ),
                  borderRadius: BorderRadius.all(
                    Radius.circular(2.0),
                  ),
                ),
                height: 42.0,
              ),
            ),

第5步:还原效果

涂鸦风格按钮的还原效果

猜你喜欢

转载自blog.csdn.net/hekaiyou/article/details/85699043