Flutter | How to show a Hint Text when a value is entered

I want the Hint Text to remain even when Text is entered in the TextField: I want to do the same

But if I give TextField something like "hintText:" in simple way, Hint Text disappears when TextField is entered: Current status.

What should I do so that the hintText doesn't disappear even when a value is entered in the TextField?

. . . I tried the following:

I. I tried using the suffix widget. But it appears from the end of the TextField. (If it was possible to make the suffix widget appear after the text, I think the problem would have been solved.) : Ignore the malfunction

II. Obviously Prefix Widget can't help here : with Prefix Widget

Any answers are welcome, thanks.

Upvotes: 4

Views: 1261

Answers (2)

Answer:

Then I looked into it and found that Telegram Messenger uses a more complex approach with custom rendering on a Canvas and animates the hint text by adjusting its opacity and position. You can check the implementation here.

But I used a simpler solution with a Stack and a monospace font: enter image description here

Here's a simple example:

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

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(18),
            child: CustomMaskedTextField(
              mask: '--- --- ----',
              style: const TextStyle(fontSize: 24, letterSpacing: 1.0),
              decoration: const InputDecoration(border: OutlineInputBorder()),
              onChanged: (value) => print('Current value: $value'),
            ),
          ),
        ),
      ),
    );
  }
}

class CustomMaskedTextField extends StatefulWidget {
  final String mask;
  final TextStyle? style;
  final InputDecoration? decoration;
  final ValueChanged<String>? onChanged;

  const CustomMaskedTextField({
    super.key,
    required this.mask,
    this.style,
    this.decoration,
    this.onChanged,
  });

  @override
  _CustomMaskedTextFieldState createState() => _CustomMaskedTextFieldState();
}

class _CustomMaskedTextFieldState extends State<CustomMaskedTextField> {
  final _inputController = TextEditingController();
  final _hintController = TextEditingController();
  late final MaskTextInputFormatter maskFormatter;

  @override
  void initState() {
    super.initState();
    maskFormatter = MaskTextInputFormatter(mask: widget.mask, filter: {"#": RegExp(r'[0-9]')});
    _inputController.addListener(_updateHintText);
    _updateHintText();
  }

  void _updateHintText() {
    final text = _inputController.text;
    final remainingMask = widget.mask.substring(text.length);
    _hintController.text = text + remainingMask;
    widget.onChanged?.call(text);
  }

  @override
  void dispose() {
    _inputController.removeListener(_updateHintText);
    _inputController.dispose();
    _hintController.dispose();
    super.dispose();
  }

  TextStyle get _baseStyle => widget.style?.copyWith(fontFamily: 'Courier') ?? const TextStyle(fontFamily: 'Courier');

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        AbsorbPointer(
          child: TextField(
            controller: _hintController,
            enabled: false,
            style: _baseStyle.copyWith(color: Colors.grey),
            decoration: widget.decoration,
          ),
        ),
        TextField(
          controller: _inputController,
          inputFormatters: [maskFormatter],
          style: _baseStyle.copyWith(color: Colors.black),
          decoration: widget.decoration,
        ),
      ],
    );
  }
}

Feel free to customize it for your use case!

Upvotes: 0

Babul
Babul

Reputation: 1224

You can use label to be visible at the top of the TextField & the hint u can simply add below line:

floatingLabelBehavior: FloatingLabelBehavior.always

full example is given below

TextFormField(
  controller: textController,
  style: theme.textTheme.bodyText2,
  keyboardType: keyboardType ?? TextInputType.number,
  enableInteractiveSelection: false,
  decoration: InputDecoration(
      labelText: labelText,
      labelStyle: theme.textTheme.headline6,
      suffixText: suffixText ?? '',
      border: OutlineInputBorder(
        borderSide:
            BorderSide(color: theme.textTheme.bodyText2.color, width: 2),
      ),
      hintText: '0.0',
      floatingLabelBehavior: FloatingLabelBehavior.always),
  validator: (value) {
    if (value.isEmpty) {
      return 'Please enter some text';
    }
    return null;
  },
  onChanged: (String text) => onChange(text),
);

Upvotes: 0

Related Questions