flutter开发实战-实现自定义按钮类似UIButton效果

最近开发过程中需要实现一下UIButton效果的flutter按钮,这里使用的是监听手势点击事件。

一、GestureDetector

GestureDetector属性定义

GestureDetector({
    super.key,
    this.child,
    this.onTapDown,
    this.onTapUp,
    this.onTap,
    this.onTapCancel,
    this.onSecondaryTap,
    this.onSecondaryTapDown,
    this.onSecondaryTapUp,
    this.onSecondaryTapCancel,
    this.onTertiaryTapDown,
    this.onTertiaryTapUp,
    this.onTertiaryTapCancel,
    this.onDoubleTapDown,
    this.onDoubleTap,
    this.onDoubleTapCancel,
    this.onLongPressDown,
    this.onLongPressCancel,
    this.onLongPress,
    this.onLongPressStart,
...

由于属性太多,我们实现onTapDown、onTapUp、onTapCancel、onTap。

二、实现flutter自定义按钮

实现自定义按钮类似,我们实现onTapDown、onTapUp、onTapCancel、onTap这几个方法

return GestureDetector(
      onTapDown: handleTapDown,
      // 处理按下事件
      onTapUp: handleTapUp,
      // 处理抬起事件
      onTap: handleTap,
      onTapCancel: handleTapCancel,
}

void handleTapDown(TapDownDetails details) {
    if (widget.enabled != null && widget.enabled == true) {
      setState(() {
        _highlighted = true;
      });
    }
  }

  void handleTapUp(TapUpDetails details) {
    setState(() {
      _highlighted = false;
    });
  }

  void handleTapCancel() {
    setState(() {
      _highlighted = false;
    });
  }

  void handleTap() {
    if (widget.enabled != null && widget.enabled == true) {
      setState(() {
        _highlighted = true;
      });
      Future.delayed(Duration(milliseconds: 100), () {
        if (mounted) {
          setState(() {
            _highlighted = false;
          });
        }
      });

      if (widget.enabled != null && widget.enabled == true) {
        widget.onPressed();
      }
    }
  }

完整代码如下

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

//枚举类的声明
enum ButtonAlignment { Center, Left, Right }

class ButtonWidget extends StatefulWidget {
  const ButtonWidget({
    Key? key,
    this.bgColor,
    this.bgHighlightedColor,
    this.color,
    this.highlightedColor,
    this.disableColor,
    this.bgDisableColor,
    this.width,
    this.height,
    this.borderRadius,
    this.buttonAlignment: ButtonAlignment.Center,
    this.text: "",
    this.textFontSize,
    this.icon,
    this.iconTextPadding,
    required this.onPressed,
    this.enabled = true,
    required this.child,
    this.border,
    this.padding,
  }) : super(key: key);

  final Color? bgColor; // 背景颜色
  final Color? bgHighlightedColor; // 背景点击高亮颜色
  final Color? color;
  final Color? highlightedColor;
  final Color? disableColor;
  final Color? bgDisableColor;
  final double? width;
  final double? height;
  final VoidCallback onPressed;
  final double? borderRadius;
  final ButtonAlignment? buttonAlignment;
  final String? text;
  final double? textFontSize;
  final Icon? icon;
  final double? iconTextPadding;
  final bool? enabled;
  final Widget child;
  final Border? border;
  final EdgeInsetsGeometry? padding;

  
  _ButtonWidgetState createState() => _ButtonWidgetState();
}

class _ButtonWidgetState extends State<ButtonWidget> {
  bool _highlighted = false;
  
  void initState() {
    // TODO: implement initState
    super.initState();
    _highlighted = false;
  }

  void handleTapDown(TapDownDetails details) {
    if (widget.enabled != null && widget.enabled == true) {
      setState(() {
        _highlighted = true;
      });
    }
  }

  void handleTapUp(TapUpDetails details) {
    setState(() {
      _highlighted = false;
    });
  }

  void handleTapCancel() {
    setState(() {
      _highlighted = false;
    });
  }

  void handleTap() {
    if (widget.enabled != null && widget.enabled == true) {
      setState(() {
        _highlighted = true;
      });
      Future.delayed(Duration(milliseconds: 100), () {
        if (mounted) {
          setState(() {
            _highlighted = false;
          });
        }
      });

      if (widget.enabled != null && widget.enabled == true) {
        widget.onPressed();
      }
    }
  }

  AlignmentGeometry showAlignment(ButtonAlignment? buttonAlignment) {
    AlignmentGeometry alignment = Alignment.center;
    if (buttonAlignment != null) {
      if (buttonAlignment == ButtonAlignment.Left) {
        alignment = Alignment.centerLeft;
      } else if (buttonAlignment == ButtonAlignment.Right) {
        alignment = Alignment.centerRight;
      } else {
        alignment = Alignment.center;
      }
    }

    return alignment;
  }

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: handleTapDown,
      // 处理按下事件
      onTapUp: handleTapUp,
      // 处理抬起事件
      onTap: handleTap,
      onTapCancel: handleTapCancel,
      child: Container(
        padding: widget.padding,
        width: widget.width,
        height: widget.height,
        alignment: showAlignment(widget.buttonAlignment),
        decoration: BoxDecoration(
          color: boxDecorationBgColor(),
          borderRadius: BorderRadius.circular(widget.borderRadius ?? 0),
          border: widget.border
        ),
        child: widget.child,
      ),
    );
  }

  Color? boxDecorationBgColor() {
    if (widget.enabled != null && widget.enabled == true) {
      return (_highlighted ? widget.bgHighlightedColor : widget.bgColor);
    }

    return widget.bgDisableColor ?? widget.bgColor;
  }

  Color? textColor() {
    if (widget.enabled != null && widget.enabled == true) {
      return (_highlighted ? widget.highlightedColor : widget.color);
    }

    return widget.disableColor ?? widget.bgColor;
  }
}

三、小结

flutter开发实战-实现自定义按钮类似UIButton效果,通过监听手势GestureDetector的onTapDown、onTapUp、onTapCancel、onTap来实现按下背景变换,松开背景恢复默认等效果。

学习记录,每天不停进步。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐