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

Flutter如何实现未聚焦时显示提示文本与标签的自定义文本框

Flutter 固定标签+hint同显文本框实现方案

Flutter 原生InputDecoration的浮动标签逻辑默认会在未输入失焦状态下让label占位到输入框内部,和hint位置冲突。要实现失焦时标签固定在输入框上方、和hint同时显示的效果,不需要修改框架源码,通过组合布局即可快速实现。

实现逻辑

  • 外层用Column做垂直排布,顶部单独放置始终显示的文本标签,标签颜色随输入框焦点状态切换
  • 输入框组件仅配置hintText属性,不设置任何label相关参数,避免触发内置的浮动标签动画
  • 通过FocusNode监听输入框焦点变化,同步更新标签、边框的显示样式,和原生Material输入框的交互体验保持一致

完整组件代码

import 'package:flutter/material.dart';

class FixedLabelTextField extends StatefulWidget {
  /// 输入框上方固定显示的标签
  final String label;
  /// 输入框内部提示文本
  final String hintText;
  final TextEditingController? controller;
  final TextInputType? keyboardType;
  final bool obscureText;
  final FormFieldValidator<String>? validator;

  const FixedLabelTextField({
    super.key,
    required this.label,
    required this.hintText,
    this.controller,
    this.keyboardType,
    this.obscureText = false,
    this.validator,
  });

  @override
  State<FixedLabelTextField> createState() => _FixedLabelTextFieldState();
}

class _FixedLabelTextFieldState extends State<FixedLabelTextField> {
  late final FocusNode _focusNode;
  bool _hasFocus = false;

  @override
  void initState() {
    super.initState();
    _focusNode = FocusNode();
    _focusNode.addListener(_handleFocusChange);
  }

  @override
  void dispose() {
    _focusNode.removeListener(_handleFocusChange);
    _focusNode.dispose();
    super.dispose();
  }

  void _handleFocusChange() {
    setState(() {
      _hasFocus = _focusNode.hasFocus;
    });
  }

  @override
  Widget build(BuildContext context) {
    final primaryColor = Theme.of(context).colorScheme.primary;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(
          widget.label,
          style: TextStyle(
            fontSize: 14,
            fontWeight: FontWeight.w500,
            color: _hasFocus ? primaryColor : Colors.grey.shade700,
          ),
        ),
        const SizedBox(height: 8),
        TextFormField(
          focusNode: _focusNode,
          controller: widget.controller,
          keyboardType: widget.keyboardType,
          obscureText: widget.obscureText,
          validator: widget.validator,
          decoration: InputDecoration(
            hintText: widget.hintText,
            hintStyle: TextStyle(
              fontSize: 14,
              color: Colors.grey.shade400,
            ),
            contentPadding: const EdgeInsets.symmetric(
              horizontal: 12,
              vertical: 14,
            ),
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(
                color: Colors.grey.shade300,
                width: 1,
              ),
            ),
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(
                color: primaryColor,
                width: 2,
              ),
            ),
            errorBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(
                color: Colors.red.shade400,
                width: 1,
              ),
            ),
            focusedErrorBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(
                color: Colors.red.shade400,
                width: 2,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

调用示例

// 页面中直接引入组件即可使用
FixedLabelTextField(
  label: "Email",
  hintText: "Enter your email address",
  keyboardType: TextInputType.emailAddress,
  validator: (val) {
    if (val == null || !val.contains('@')) return 'Please enter valid email';
    return null;
  },
)

效果说明:

  • 未聚焦状态下,输入框上方标签、框内hint文本同时展示,完全匹配需求
  • 聚焦时标签自动切换为主题色,输入框边框高亮,交互逻辑和原生输入框无差异
  • 保留了原生输入框的所有能力,包括表单校验、密码模式、输入格式限制等,可直接复用业务逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:31:02