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

Flutter中如何在onChanged时根据验证动态修改TextField边框颜色?

Flutter 实时验证输入并动态修改 TextField 边框颜色

核心逻辑很明确:监听输入内容变化,实时执行邮箱/手机号规则验证,根据验证结果更新状态,最终同步到 TextField 的边框样式上。下面是三种主流状态管理方案的落地实现:

一、GetX 实现

1. 编写 GetX 控制器

import 'package:get/get.dart';

class InputController extends GetxController {
  final RxString inputText = ''.obs;
  bool isEmailMode = true; // 可根据业务场景切换验证模式
  final RegExp emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');

  Color get borderColor {
    if (isEmailMode) {
      return emailRegex.hasMatch(inputText.value) ? Colors.white : Colors.red;
    } else {
      return inputText.value.length == 10 ? Colors.white : Colors.red;
    }
  }

  void updateInput(String text) {
    inputText.value = text;
  }

  void toggleMode() {
    isEmailMode = !isEmailMode;
    update();
  }
}

2. UI 层集成

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

class InputPage extends StatelessWidget {
  final InputController controller = Get.put(InputController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          Obx(() => TextButton(
                onPressed: controller.toggleMode,
                child: Text(controller.isEmailMode ? '切换到手机号' : '切换到邮箱'),
              ))
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Obx(
          () => TextField(
            onChanged: controller.updateInput,
            decoration: InputDecoration(
              border: OutlineInputBorder(
                borderSide: BorderSide(color: controller.borderColor),
              ),
              focusedBorder: OutlineInputBorder(
                borderSide: BorderSide(color: controller.borderColor),
              ),
              hintText: controller.isEmailMode ? '输入邮箱' : '输入手机号',
            ),
          ),
        ),
      ),
    );
  }
}

二、Provider 实现

1. 创建 ChangeNotifier 类

import 'package:flutter/material.dart';

class InputProvider extends ChangeNotifier {
  String _inputText = '';
  bool isEmailMode = true;
  final RegExp emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');

  String get inputText => _inputText;

  Color get borderColor {
    if (isEmailMode) {
      return emailRegex.hasMatch(_inputText) ? Colors.white : Colors.red;
    } else {
      return _inputText.length == 10 ? Colors.white : Colors.red;
    }
  }

  void updateInput(String text) {
    _inputText = text;
    notifyListeners();
  }

  void toggleMode() {
    isEmailMode = !isEmailMode;
    notifyListeners();
  }
}

2. UI 层集成

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

class InputPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => InputProvider(),
      child: Scaffold(
        appBar: AppBar(
          actions: [
            Consumer<InputProvider>(
              builder: (context, provider, child) {
                return TextButton(
                  onPressed: provider.toggleMode,
                  child: Text(provider.isEmailMode ? '切换到手机号' : '切换到邮箱'),
                );
              },
            )
          ],
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Consumer<InputProvider>(
            builder: (context, provider, child) {
              return TextField(
                onChanged: provider.updateInput,
                decoration: InputDecoration(
                  border: OutlineInputBorder(
                    borderSide: BorderSide(color: provider.borderColor),
                  ),
                  focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: provider.borderColor),
                  ),
                  hintText: provider.isEmailMode ? '输入邮箱' : '输入手机号',
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

三、Bloc 实现

1. 定义事件与状态

import 'package:bloc/bloc.dart';

// 输入变化事件
class InputChangedEvent {
  final String text;
  final bool isEmailMode;

  InputChangedEvent(this.text, this.isEmailMode);
}

// 输入状态
class InputState {
  final String inputText;
  final bool isEmailMode;
  final Color borderColor;

  InputState({
    required this.inputText,
    required this.isEmailMode,
    required this.borderColor,
  });
}

// Bloc 核心逻辑
class InputBloc extends Bloc<InputChangedEvent, InputState> {
  final RegExp emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');

  InputBloc() : super(InputState(inputText: '', isEmailMode: true, borderColor: Colors.red)) {
    on<InputChangedEvent>((event, emit) {
      Color color;
      if (event.isEmailMode) {
        color = emailRegex.hasMatch(event.text) ? Colors.white : Colors.red;
      } else {
        color = event.text.length == 10 ? Colors.white : Colors.red;
      }
      emit(InputState(
        inputText: event.text,
        isEmailMode: event.isEmailMode,
        borderColor: color,
      ));
    });
  }
}

2. UI 层集成

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

class InputPage extends StatefulWidget {
  @override
  State<InputPage> createState() => _InputPageState();
}

class _InputPageState extends State<InputPage> {
  bool _isEmailMode = true;

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) => InputBloc(),
      child: Scaffold(
        appBar: AppBar(
          actions: [
            TextButton(
              onPressed: () {
                setState(() {
                  _isEmailMode = !_isEmailMode;
                  // 切换模式后触发一次验证更新
                  context.read<InputBloc>().add(InputChangedEvent(context.read<InputBloc>().state.inputText, _isEmailMode));
                });
              },
              child: Text(_isEmailMode ? '切换到手机号' : '切换到邮箱'),
            )
          ],
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: BlocBuilder<InputBloc, InputState>(
            builder: (context, state) {
              return TextField(
                onChanged: (text) {
                  context.read<InputBloc>().add(InputChangedEvent(text, _isEmailMode));
                },
                decoration: InputDecoration(
                  border: OutlineInputBorder(
                    borderSide: BorderSide(color: state.borderColor),
                  ),
                  focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: state.borderColor),
                  ),
                  hintText: _isEmailMode ? '输入邮箱' : '输入手机号',
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

以上三种方案均能实现实时验证输入并动态调整边框颜色的需求,可根据项目技术栈自由选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:10:38