You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现TextFormField获取焦点时显示渐变边框

Flutter实现TextFormField点击时渐变边框效果问题

OutlinedInputBorder不支持将LinearGradient作为颜色值,我尝试实现点击TextFormField时边框显示渐变效果,但代码没有生效,相关代码如下:

GestureDetector(
  onTap: () {
    setState(() {
      borderFocused = true;
    });
  },
  child: Container(
    decoration: borderFocused
        ? const BoxDecoration(
            border: GradientBoxBorder(
                gradient: LinearGradient(
            colors: [
              Color(0xff45a7f5),
              Color(0xff76c479)
            ],
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
          )))
        : BoxDecoration(
            border: Border(
                bottom: BorderSide(
                    color: Color.fromARGB(
                        30, 192, 192, 192)))),
    child: TextFormField(
      cursorColor: Color.fromARGB(255, 192, 192, 192),
      style: const TextStyle(
          color: Color.fromARGB(255, 192, 192, 192)),
      decoration: textInputDecoration.copyWith(
          labelStyle: const TextStyle(
              color: Color.fromARGB(255, 192, 192, 192)),
          hintText: "Email",
          prefixIcon: Icon(
            Icons.email,
            color: Theme.of(context).primaryColor,
          )),
    ),
  ),
)

问题分析

你的代码存在两个核心问题:

  1. TextFormField自带的decoration会覆盖外层Container的边框样式,导致渐变边框被遮挡
  2. 使用GestureDetector监听点击无法完全匹配输入框的焦点状态(比如通过键盘切换焦点时不会触发)

解决方案

通过FocusNode监听输入框焦点,结合Stack实现渐变边框效果,完整代码如下:

class GradientBorderEmailField extends StatefulWidget {
  const GradientBorderEmailField({super.key});

  @override
  State<GradientBorderEmailField> createState() => _GradientBorderEmailFieldState();
}

class _GradientBorderEmailFieldState extends State<GradientBorderEmailField> {
  late FocusNode _emailFocusNode;
  bool _isFocused = false;

  @override
  void initState() {
    super.initState();
    _emailFocusNode = FocusNode();
    // 监听焦点变化
    _emailFocusNode.addListener(() {
      setState(() {
        _isFocused = _emailFocusNode.hasFocus;
      });
    });
  }

  @override
  void dispose() {
    _emailFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        // 渐变边框容器(仅在聚焦时显示)
        if (_isFocused)
          Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(8),
              gradient: const LinearGradient(
                colors: [Color(0xff45a7f5), Color(0xff76c479)],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
            ),
            child: Container(
              margin: const EdgeInsets.all(1), // 控制边框宽度
              decoration: const BoxDecoration(
                color: Colors.white, // 与输入框背景色保持一致
                borderRadius: BorderRadius.circular(7),
              ),
            ),
          ),
        // TextFormField主体
        TextFormField(
          focusNode: _emailFocusNode,
          cursorColor: const Color.fromARGB(255, 192, 192, 192),
          style: const TextStyle(color: Color.fromARGB(255, 192, 192, 192)),
          decoration: InputDecoration(
            labelStyle: const TextStyle(color: Color.fromARGB(255, 192, 192, 192)),
            hintText: "Email",
            prefixIcon: Icon(Icons.email, color: Theme.of(context).primaryColor),
            // 配置边框样式
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: _isFocused ? BorderSide.none : const BorderSide(
                color: Color.fromARGB(30, 192, 192, 192),
                width: 1,
              ),
            ),
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: const BorderSide(
                color: Color.fromARGB(30, 192, 192, 192),
                width: 1,
              ),
            ),
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide.none, // 聚焦时隐藏默认边框
            ),
            fillColor: Colors.white,
            filled: true,
            contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
          ),
        ),
      ],
    );
  }
}

关键说明

  • 用FocusNode替代GestureDetector,能准确捕捉输入框的所有焦点变化场景(点击、键盘切换等)
  • 通过Stack将渐变边框容器放在输入框下方,聚焦时显示渐变层,非聚焦时显示默认灰色边框
  • 渐变容器内部的margin控制边框宽度,确保输入框内容不会被边框遮挡
  • 隐藏输入框聚焦时的默认边框,避免与渐变边框重叠冲突

内容的提问来源于stack exchange,提问作者anotheruser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:40:19