Home > database >  Add a dash automatically after 5 characters
Add a dash automatically after 5 characters

Time:03-31

I want to format pin entry with a dash after at least 5 characters have been entered. So, each user enter the 10 digit pin code a dash is added automatically after every 5 characters.

TextField(
                      maxLength: 10,
                      keyboardType: TextInputType.text,
                      textCapitalization: TextCapitalization.characters,

                      onChanged: (text) {
                        pin = text;
                      },
                      textAlign: TextAlign.left,
                      // keyboardType: TextInputType.visiblePassword,
                      decoration: InputDecoration(
                        errorText: _errorText,
                        icon: Icon(
                          Icons.dialpad,
                        ),
                        labelText: '8-digit PIN',
                        contentPadding: EdgeInsets.symmetric(vertical: 10.0),
                        focusedBorder: UnderlineInputBorder(
                          borderSide:
                              BorderSide(color: Colors.transparent, width: 2),
                        ),
                        focusedErrorBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Colors.red, width: 2),
                        ),
                        errorBorder: UnderlineInputBorder(
                          borderSide:
                              BorderSide(color: Color(0xFFF696969), width: 1),
                        ),
                      ),
                    ),

CodePudding user response:

Try my solution. It a) lets you delete entered dashes again and b) keeps the cursor at the right place and c) works with as many dashes as you like

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController controller = TextEditingController();
  String pin = "";
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.white,
        body: TextField(
          controller: controller,
          maxLength: 10,
          keyboardType: TextInputType.text,
          textCapitalization: TextCapitalization.characters,

          onChanged: (text) {
            if(text.length > pin.length){
              final String newText = _addDashes(text);
              controller.text = newText;
              controller.selection = TextSelection.collapsed(offset: newText.length); 
            }
            pin = text;
          },
          textAlign: TextAlign.left,
          // keyboardType: TextInputType.visiblePassword,
          decoration: const InputDecoration(
            errorText: "",
            icon: Icon(
              Icons.dialpad,
            ),
            labelText: '8-digit PIN',
            contentPadding: EdgeInsets.symmetric(vertical: 10.0),
            focusedBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.transparent, width: 2),
            ),
            focusedErrorBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.red, width: 2),
            ),
            errorBorder: UnderlineInputBorder(
              borderSide: BorderSide(color: Color(0xFFF69696), width: 1),
            ),
          ),
        ),
      ),
    );
  }
  
  String _addDashes(String text){
    const int addDashEvery = 5;
    text = text.replaceAll("-", "");
    String dashedText = "";
    for(int i = 0; i < text.length; i  ){
      dashedText =text[i];
      if((i   1) % addDashEvery == 0){
        dashedText ="-";
      }
    }
    return dashedText;
  }
}

CodePudding user response:

You should add a controller to your TextField, so you can control the value of the text field.

TextField(
...
  controller: _controller,
...
)

Change your onChange event function to something like this:

onChanged: (String text) {
  final sanitizedText = text.replaceAll('-', '');

  _controller.text = _addDashes(sanitizedText);
},

This takes the current text inside the TextField, removes the dashes, and stores it in a variable. Then the function replaces the text of the TextField using the controller, to the value of the sanitized text with _addDashes function applied to it:

String _addDashes(String text) {
  const int addDashEvery = 5;
  String out = '';
  
  for (int i = 0; i < text.length; i  ) {
    if (i   1 > addDashEvery && i % addDashEvery == 0) {
      out  = '-';
    }
    
    out  = text[i];
  }
  
  return out;
}

CodePudding user response:

You can try this approach, use TextEditingController to controller when the text reaches an specific length and _controller.selection to continue where the dash was added, if this selection property is not handled then the selection will be restarted to the beginning:

class _MyHomePageState extends State<MyHomePage> {

  final TextEditingController _controller = TextEditingController();
  late FocusNode myFocusNode;

  @override
  void initState() {

    myFocusNode = FocusNode();
    _controller.addListener(() {

      if(_controller.text.length == 4) {
        _controller.text = _controller.text   '-';
        _controller.selection = TextSelection.fromPosition(TextPosition(offset: _controller.text.length));;
      }

    });

    super.initState();
  }

  @override
  void didChangeDependencies() {
    print(_controller.text);
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    _controller.dispose();
    myFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.lightBlue,
      body: Container(
        child: SingleChildScrollView(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [

                TextField(
                  maxLength: 10,
                  keyboardType: TextInputType.text,
                  textCapitalization: TextCapitalization.characters,
                  controller: _controller,
                  focusNode: myFocusNode,
                  onChanged: (text) {},
                  textAlign: TextAlign.left,
                  decoration: const InputDecoration(
                    icon: Icon(
                      Icons.dialpad,
                    ),
                    labelText: '8-digit PIN',
                    contentPadding: EdgeInsets.symmetric(vertical: 10.0),
                    focusedBorder: UnderlineInputBorder(
                      borderSide:
                      BorderSide(color: Colors.transparent, width: 2),
                    ),
                    focusedErrorBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: Colors.red, width: 2),
                    ),
                    errorBorder: UnderlineInputBorder(
                      borderSide:
                      BorderSide(color: Color(0xFFF696969), width: 1),
                    ),
                  ),
                ),

              ],
            ),
          ),
        ),
      ),

    );
  }

}
  • Related