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

实现TextField聚焦时AppBar背景色从1%透明度黑色切换为纯黑色

实现TextField聚焦时AppBar背景色从1%透明度黑色切换为纯黑色

看起来你已经把UI的其他部分都搞定了,就差AppBar在输入框聚焦时的颜色切换对吧?我来给你捋个简单的实现思路,核心就是监听输入框的焦点状态,然后通知父页面更新AppBar的颜色。

第一步:在登录页面的State类里添加状态变量

先在_MyLoginPageState里定义一个布尔变量,用来标记是否有输入框处于聚焦状态,同时把AppBar的背景色和这个变量绑定:

class _MyLoginPageState extends State<MyLoginPage> {
  AppAssets appAssets = AppAssets();
  bool _isInputFocused = false; // 新增状态变量,标记输入框是否聚焦

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backgroundColor,
      appBar: AppBar(
        // 根据焦点状态切换颜色:聚焦时纯黑,否则1%透明黑
        backgroundColor: _isInputFocused ? Colors.black : Colors.black.withOpacity(0.01),
        centerTitle: true,
        title: Text(
          'Login',
          style: AppTextStyles.heading(),
        ),
      ),
      // ... 其他原有代码保持不变
    );
  }
}

第二步:给MyInput组件添加焦点回调

因为你的MyInput是StatelessWidget,我们需要给它加一个回调函数,让它能把内部TextField的焦点变化通知给父页面。修改MyInput的代码:

class MyInput extends StatelessWidget {
  final String placeholder;
  // 新增焦点变化回调,用来通知父页面焦点状态
  final void Function(bool)? onFocusChange;

  const MyInput({super.key, required this.placeholder, this.onFocusChange});

  @override
  Widget build(BuildContext context) {
    // 创建FocusNode监听TextField的焦点状态
    final focusNode = FocusNode();

    // 添加焦点监听器
    focusNode.addListener(() {
      // 把当前焦点状态传递给父页面
      onFocusChange?.call(focusNode.hasFocus);
    });

    return ClipRRect(
      borderRadius: borderRadius10,
      child: ConstrainedBox(
        constraints: const BoxConstraints(
          maxWidth: 350,
          maxHeight: 66.66,
          minWidth: 315,
          minHeight: 60,
        ),
        child: BackdropFilter(
          filter: ImageFilter.blur(sigmaX: blur300, sigmaY: blur300),
          child: Container(
            decoration: BoxDecoration(
              color: backgroundColor.withOpacity(0.2),
              borderRadius: borderRadius10,
            ),
            child: TextField(
              focusNode: focusNode, // 将FocusNode绑定到TextField
              cursorColor: textPrimary,
              cursorOpacityAnimates: true,
              enableSuggestions: true,
              style: AppTextStyles.body(),
              decoration: InputDecoration(
                filled: true,
                fillColor: Colors.transparent,
                hintText: placeholder,
                hintStyle: AppTextStyles.body(),
                border: const OutlineInputBorder(borderSide: BorderSide.none)),
            ),
          ),
        ),
      ),
    );
  }
}

第三步:在父页面中给MyInput绑定回调

回到_MyLoginPageState的build方法里,使用MyInput时传入焦点变化的回调,触发状态更新:

ConstrainedBox(
  constraints: const BoxConstraints(maxHeight: 300, minHeight: 280),
  child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      MyInput(
        placeholder: 'Username',
        onFocusChange: (isFocused) {
          setState(() {
            _isInputFocused = isFocused;
          });
        },
      ),
      MyInput(
        placeholder: 'Password',
        onFocusChange: (isFocused) {
          setState(() {
            _isInputFocused = isFocused;
          });
        },
      ),
    ],
  ),
),

为什么之前的surfaceTintColor和elevation没用?

因为你要改的是AppBar的背景色透明度,而surfaceTintColor是Material3中用来覆盖AppBar表面色调的属性,elevation是控制阴影高度的属性,这两个都和背景色的透明度切换无关,所以调整它们自然没效果啦。

这样改完之后,当你点击任意一个输入框聚焦时,AppBar就会变成纯黑色,失焦时回到1%透明的黑色,完全符合你的需求~

备注:内容来源于stack exchange,提问作者Param

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 07:28:11