(Flutter) TextFormField Изменить labelColor в фокусе

Я пытаюсь изменить свой labelText цвет, когда сфокусирован. Я могу изменить цвет текста, но не в фокусе.

Я перепробовал все цвета текста подсказки и цвета текста меток, но ничего не помогает.

Container(
  padding: EdgeInsets.fromLTRB(15, 10, 15, 0),
  child: TextFormField(
    cursorColor: Colors.lightGreen,
    keyboardType: TextInputType.phone,
    decoration: InputDecoration(
      labelText: 'Phone Number',
      hintText: 'Enter a Phone Number',
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(
          color: Colors.lightGreen
        )
      ),
      border: OutlineInputBorder(
        borderSide: BorderSide()
      ),
    )
  ),
),

Вот изображения происходящего:

введите описание изображения здесь

введите описание изображения здесь


person Bnd10706    schedule 02.06.2019    source источник
comment
Вы пытаетесь изменить цвет labelText или hintText в целом, или вы просите, чтобы он был одним цветом, когда он не в фокусе, и другим, когда в фокусе?   -  person Adrian Murray    schedule 02.06.2019
comment
Я хочу изменить цвет labelText, как только он окажется в фокусе. Если вы видите на моих фотографиях, текст метки серый, когда не выбран (что я хочу), а затем, когда я выберу его, я хочу, чтобы он стал черным (он становится синим)   -  person Bnd10706    schedule 02.06.2019


Ответы (11)


Вам понадобится способ определить его состояние фокуса, а затем на его основе создать условное выражение для его цвета. Вот где focusNode было бы полезно. Создайте новый FocusNode из создания виджета, используйте его как свойство focusNode в TextFormField. Затем в свойстве цвета свойства TextStyle объекта TextFormField вы можете добавить что-то вроде:

FocusNode myFocusNode = new FocusNode();

...

  return TextFormField(
    focusNode: myFocusNode,
    decoration: InputDecoration(
      labelText: 'test',
      labelStyle: TextStyle(
        color: myFocusNode.hasFocus ? Colors.blue : Colors.black
      )
    ),
  );

РЕДАКТИРОВАТЬ: Просто небольшое примечание, вам, вероятно, нужно убедиться, что это находится в StatefulWidget, а затем добавить слушателя к focusNode, который вы создали, и вызвать setState для любых событий в этом focusNode. В противном случае вы не увидите никаких изменений.

person Adrian Murray    schedule 02.06.2019
comment
это не сработало. Я добавил узел фокуса, как вы сказали, и последовал вашему примеру. LabelStyle остался того же цвета, погода в фокусе или нет. - person Bnd10706; 02.06.2019
comment
хамм .. вы говорите, что набор вызовов установлен на labelText? - person Bnd10706; 02.06.2019
comment
Вы не устанавливаетеState для свойства, вы вызываете его для события, которое вызывает перестройку всего виджета / класса. Вы вызываете setState в событии фокуса. Это можно сделать, например, добавив слушателя в initState. Например: myFocusNode.addListener (() {setState (() {});}) не забудьте избавиться от ваших слушателей, чтобы предотвратить утечку памяти. - person Adrian Murray; 02.06.2019
comment
отлично, вот и все. Спасибо! - person Bnd10706; 02.06.2019
comment
Я впервые использую слушателя (извините, я новичок, где мне избавиться от слушателя? - person Bnd10706; 02.06.2019
comment
вы переопределяете метод dispose () так же, как и initState (). Вам нужно будет сделать функцию () {} собственной переменной, а затем вызвать ее в методах addListener и removeListener созданного вами focusNode. Это, вероятно, лучше прочитать подробно, а не мое быстрое объяснение. - person Adrian Murray; 02.06.2019
comment
Я буду, я ценю это! - person Bnd10706; 02.06.2019
comment
Хорошо, я обнаружил проблему .... У меня есть 6 разных форм, и когда я добавляю узел фокуса в формы, они вызывают переход в фокус. Мне не нужно делать 6 разных фокусных узлов? - person Bnd10706; 02.06.2019
comment
да, каждый узел фокуса предназначен для каждого поля. Вот как вы определяете, где вы фокусируетесь или где установить фокус, если вы хотите программно переместить фокус пользователя. Вариант, который вы можете рассмотреть, - создать свой собственный класс, который объединит все функции изменения цвета при фокусировке / расфокусировке в одном месте. Затем используйте этот класс как способ создания текстовых полей. На самом деле это было бы немного эффективнее, поскольку тогда вы вызывали бы перестройку только каждого текстового поля в событиях смены фокуса, а не всей формы / страницы. - person Adrian Murray; 02.06.2019
comment
Этот метод работает для изменения цвета текстового поля при фокусировке, но цвет не возвращается к исходному при размытии. Любые идеи? Спасибо! - person rob_; 08.06.2020

The Summary

Возможно, вы захотите ознакомиться с рецептом Фокус и текстовые поля Flutter Cookbook.

По сути, мы должны:

  1. Создайте свойство FocusNode.
  2. Добавьте к нему инициализацию и удаление.
  3. Добавьте его в TextFormField.
  4. Добавляйте запрос на фокус при каждом нажатии на TextFormField.

1. Create a FocusNode property

class CustomTextFormFieldState extends State<CustomTextFormField> {
  FocusNode _focusNode;
  ...

2. Add initialization and disposal to it

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

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

3. Add it to the TextFormField

@override
Widget build(BuildContext context) {
  return TextFormField(
    focusNode: _focusNode,
    ...

4. Add a focus request on every tap on the TextFormField

Не забудьте использовать setState:

void _requestFocus(){
  setState(() {
    FocusScope.of(context).requestFocus(_focusNode);
  });
}

Добавьте метод в свойство TextFormField onTap:

@override
Widget build(BuildContext context) {
  return TextFormField(
    focusNode: _focusNode,
    onTap: _requestFocus,
    ...
person Philippe Fanaro    schedule 09.03.2020

Вот быстрый метод без использования виджета с отслеживанием состояния

 return Theme( // 1) wrap with theme widget
   data: Theme.of(context).copyWith(primaryColor: //2) color you want here)
   child: TextFormField(
     focusNode: myFocusNode,
     decoration: InputDecoration(
    labelText: 'test',      
    ),
   ),
  );
person David Machara    schedule 27.10.2020
comment
Текст несфокусированной метки - hintColor:. Но это не сработает, если вы используете свойство цвета TextStyle в свойстве hintText объекта InputDecoration. Не могу сказать, почему нет ... - person th_lo; 18.03.2021
comment
Это самый простой способ заставить его работать. Спасибо. - person DavidMM; 04.06.2021

Быстрое решение - изменить primarySwatch с theme виджета MaterialApp. Единственный недостаток - требуется Material Color.

на изображении текстового поля в фокусе

введите описание изображения здесь

person Classy-Bear    schedule 20.04.2020

Решаю эту проблему виджетом Focus. Сначала я определил переменную цвета для каждого поля:

final _lowColor = Colors.amber[50];   // use your own colors
final _highColor = Colors.amber[200];

Color _field1Color = _lowColor;
Color _field2Color = _lowColor;
...

Затем я обернул каждый TextFormField виджетом Focus и изменил fieldColor:

child: Focus(
  onFocusChange: (hasFocus) {
    setState(() => _field1Color = hasFocus ? _highColor : _lowColor);
  },
  child: TextFormField(
    ...
      color: _field1Color,
    ...
    ),
  ), 
),
person oibees    schedule 25.02.2021
comment
Это очень хорошо работает - person baliman; 09.04.2021
comment
Идеально сработал для меня! - person Ankit Chawla; 19.05.2021

Update

Как упоминалось в комментарии Гильерме, более поздняя версия Flutter использует другую логику для получения цвета.

Color _getActiveColor(ThemeData themeData) {
  if (isFocused) {
    return themeData.colorScheme.primary;
  }
  return themeData.hintColor;
}

ThemeData.dark().copyWith( colorScheme: ColorScheme.dark( primary: activeColor, ), )


Original answer

Покопавшись в исходном коде InputDecorator, используемого для определения цвета метки, я нашел вот что.

TextStyle _getFloatingLabelStyle(ThemeData themeData) {
  final Color color = decoration.errorText != null
    ? decoration.errorStyle?.color ?? themeData.errorColor
    : _getActiveColor(themeData);
  final TextStyle style = themeData.textTheme.subtitle1.merge(widget.baseStyle);
  return style
    .copyWith(color: decoration.enabled ? color : themeData.disabledColor)
    .merge(decoration.labelStyle);
}

Color _getActiveColor(ThemeData themeData) {
  if (isFocused) {
    switch (themeData.brightness) {
      case Brightness.dark:
        return themeData.accentColor;
      case Brightness.light:
        return themeData.primaryColor;
    }
  }
  return themeData.hintColor;
}

Короче говоря, чтобы изменить цвет метки, установите primaryColor светлую тему или accentColor для темной темы.

Еще один совет: чтобы изменить цвет метки, когда она не сфокусирована, установите hintColor.

ThemeData.dark().copyWith(
  primaryColor: Colors.red,
  accentColor: Colors.white,
  hintColor: Colors.pink,
)
person Yaobin Then    schedule 15.05.2020

вы также можете использовать labelStyle, когда текстовое поле находится в фокусе и если текстовое поле ошибочно (вызвано несоблюдением проверки)

labelText: 'Password',
     labelStyle: TextStyle(
        color: Colors.black54,
          ),
//when error has occured
     errorStyle: TextStyle(
       color: Colors.black,
         ),
person Masudha Meher    schedule 05.08.2020

Вы можете обернуть текстовое поле Theme и установить в качестве основного цвета любой цвет метки.

person Munashif Muhsin    schedule 02.09.2020
comment
Просто и работоспособно. Спасибо и хорошего дня! - person F-Y; 28.06.2021

В разделе «decoration» есть lableStyle, например:

labelText: 'Description',
labelStyle: TextStyle(
  color: Colors.lightBlueAccent,
)),
person Javen    schedule 16.11.2020

Если вы хотите изменить основной цвет. Просто определите добавить primaryColor из Widget MaterialApp.

const appPrimaryColor = Color(0xFF746DF7);
ThemeData theme() {
  return ThemeData(
    scaffoldBackgroundColor: Colors.white,
    fontFamily: "Inter",
    appBarTheme: appBarTheme(),
    textTheme: textTheme(),
    inputDecorationTheme: inputDecorationTheme(),
    visualDensity: VisualDensity.adaptivePlatformDensity,
    primaryColor: appPrimaryColor // <------ HERE
  );
}

MaterialApp(
   title: 'Flutter Demo',
   theme: theme(), // <------ HERE
   home: SplashScreen(),
   routes: routes,
)

введите описание изображения здесь

person Phat Tran Ky    schedule 14.03.2021

Решил проблему с помощью виджета StatefulWidget и Focus. Я использую StatefulWidget, потому что вам нужно использовать setState для уведомления об изменении цвета при фокусировке на вводе.

введите описание изображения здесь

class InputEmail extends StatefulWidget {
  @override
  _InputEmailState createState() => _InputEmailState();
}

class _InputEmailState extends State<InputEmail> {
  Color _colorText = Colors.black54;

  @override
  Widget build(BuildContext context) {
    const _defaultColor = Colors.black54;
    const _focusColor = Colors.purple;

    return Container(
      padding: EdgeInsets.symmetric(vertical: 15),
      child: Focus(
        onFocusChange: (hasFocus) {
          // When you focus on input email, you need to notify the color change into the widget.
          setState(() => _colorText = hasFocus ? _focusColor : _defaultColor);
        },
        child: TextField(
          // Validate input Email
          keyboardType: TextInputType.emailAddress,
          
          decoration: InputDecoration(
            hintText: '[email protected]',
            labelText: 'Email',
            labelStyle: TextStyle(color: _colorText),
            
            // Default Color underline
            enabledBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.black26),
            ),

            // Focus Color underline
            focusedBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.purple),
            ),
            icon: Icon(
              Icons.mail,
              color: Colors.deepPurpleAccent,
            ),
          ),
        ),
      ),
    );
  }
}

person Gleny    schedule 02.05.2021