TextField 글자수 제한하기

Chocomilk·2021년 1월 19일
1
post-thumbnail
  • TextField의 글자수 제한 방법
    1) maxLength : 5 / maxLengthEnforced : true
    2) inputFormatters:[LengthLimitingTextInputFormatter(10)]

하지만 위의 방법을 적용해도 다음과 같은 결과가 일어난다.

위와 같이 설정 글자수 초과시 UI에 표현만 되고 글자수는 제한 되지 않는다.

이를 해결하기 위한 방법으로 두 가지가 있다(내가 발견한)

1. 아래와 같이 Custom InputFormatter를 작성 & 적용.

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/services.dart';
import 'dart:math';
import 'dart:convert';

class Utf8LengthLimitingTextInputFormatter extends TextInputFormatter {
  Utf8LengthLimitingTextInputFormatter(this.maxLength)
      : assert(maxLength == null || maxLength == -1 || maxLength > 0);

  final int maxLength;

  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue,
      TextEditingValue newValue,
      ) {
    if (maxLength != null &&
        maxLength > 0 &&
        bytesLength(newValue.text) > maxLength) {
      // If already at the maximum and tried to enter even more, keep the old value.
      if (bytesLength(oldValue.text) == maxLength) {
        return oldValue;
      }
      return truncate(newValue, maxLength);
    }
    return newValue;
  }

  static TextEditingValue truncate(TextEditingValue value, int maxLength) {
    var newValue = '';
    if (bytesLength(value.text) > maxLength) {
      var length = 0;

      value.text.characters.takeWhile((char) {
        var nbBytes = bytesLength(char);
        if (length + nbBytes <= maxLength) {
          newValue += char;
          length += nbBytes;
          return true;
        }
        return false;
      });
    }
    return TextEditingValue(
      text: newValue,
      selection: value.selection.copyWith(
        baseOffset: min(value.selection.start, newValue.length),
        extentOffset: min(value.selection.end, newValue.length),
      ),
      composing: TextRange.empty,
    );
  }

  static int bytesLength(String value) {
    return utf8.encode(value).length;
  }
}

코드 출처 - https://dev.to/stack-labs/flutter-utf8-textfield-length-limiter-and-char-counter-31o7


코드를 간단히 해석해보자면 다음과 같다.

  • TextField를 통해 text를 입력받는다.
  • 만약 설정한 Text의 길이(바이트)에 도달했을 경우 이후에 입력받는 Text들의 값은 추가되지 않는다.
  • 위의 경우 TextFormField의 Input값을 byte로 계산하여 Input길이를 제한한다!
    (참고 : 영어/숫자 - 1바이트 , 한글 - 3바이트 / 이모티콘 - 4바이트)

위의 코드 작성후 적용하고자 하는 TextField에 다음과 같이 사용하면 된다!

 TextField(
   controller : TextEditingController(),
   inputFormatters: [Utf8LengthLimitingTextInputFormatter(5)],
   )

-> 5 대신 본인이 제한하고자 하는 길이만큼 써주면 된다.


2. 아래와 같이 onChanged와 InputFormatters 동시 적용

TextFormField(
           focusNode: _focusNode,
           textAlign: TextAlign.center,
           onChanged: (nextText){
             setState(() {
              if(_searchController.text.trim() != ""){
                isSelected = true;
              }else{
                isSelected = false;
              }
                _searchController.text = nextText.substring(0,maxLength);
              _searchController.selection = TextSelection.fromPosition(TextPosition(offset: maxLength));

             });
               },
           inputFormatters: [
             LengthLimitingTextInputFormatter(maxLength)
           ],
),

코드를 간단히 해석해보자면 다음과 같다.

  • TextFormField를 통해 text를 입력받는다.
  • onChanged에서 text길이 검사 - 설정 길이 이상일 경우 그 이상은 제거
  • controller.selection : TextFormField의 커서 위치 설정
profile
어제보다 한 발짝 더 나아가려는 Flutter 개발자

0개의 댓글