개발노트

19. [Flutter] TextField 텍스트 입력 창 다루기(with TextEditingController, AnimatedContainer) 본문

앱 개발/Flutter

19. [Flutter] TextField 텍스트 입력 창 다루기(with TextEditingController, AnimatedContainer)

mroh1226 2023. 6. 16. 14:00
반응형

사용자로 부터 문자 입력을 받을 때 사용하는 TextField 위젯을 알아보도록 하겠습니다.

또한, TextField 위젯에 입력된 값을 받아오는 TextEditingController 을 활용해보겠습니다.


TextField

  • 텍스트 입력: 사용자가 텍스트를 입력할 수 있는 입력 필드를 제공합니다. 사용자는 키보드를 사용하여 텍스트를 입력할 수 있습니다.
  • 힌트(Placeholder): 텍스트 필드에 입력될 내용을 설명하는 힌트를 제공할 수 있습니다. 힌트는 보통 회색 또는 다른 색상으로 표시되며, 사용자가 실제로 텍스트를 입력하기 전까지 힌트가 표시됩니다.
  • 이벤트 처리: 텍스트 필드에서 텍스트가 변경되거나 사용자가 텍스트를 입력하는 등의 이벤트를 처리할 수 있습니다. 이를 통해 텍스트 필드에 대한 유효성 검사, 자동완성 기능, 검색 기능 등을 구현할 수 있습니다.
  • 텍스트 제한: 일부 TextField 위젯은 사용자가 입력할 수 있는 최대 길이를 제한하는 기능을 제공합니다. 이를 통해 텍스트 필드에 입력되는 텍스트의 길이를 제한할 수 있습니다.
TextField(
  maxLength: 10,
  //문자열 수 10으로 제한
  inputFormatters: [
    FilteringTextInputFormatter.deny(RegExp(r'[ㄱ-ㅎㅏ-ㅣ가-힣]'))
    //한글 입력 막기
  ],
  controller: _usernameController,
  cursorColor: Theme.of(context).primaryColor,
  decoration: const InputDecoration(
      hintText: 'Insert Your Name',
      hintStyle: TextStyle(color: Colors.grey),
      focusedBorder: UnderlineInputBorder(
          borderSide: BorderSide(color: Colors.black, width: 2)),
      enabledBorder: UnderlineInputBorder(
          borderSide: BorderSide(color: Colors.grey))),
),
  • maxLength: 10: 이 속성은 TextField에서 입력할 수 있는 최대 문자열 길이를 10으로 제한합니다. 사용자는 10자 이상의 문자를 입력할 수 없습니다.
  • inputFormatters: 이 속성은 TextField에서 입력을 제한하거나 변형하는 데 사용됩니다. 위의 예시에서는 FilteringTextInputFormatter.deny(RegExp(r'[ㄱ-ㅎㅏ-ㅣ가-힣]'))을 사용하여 한글 입력을 막습니다. 입력 중에 한글이 포함되면 입력이 거부됩니다.
  • controller: _usernameController: 이 속성은 TextField에 대한 TextEditingController를 지정합니다. _usernameController는 사용자가 입력한 텍스트를 추적하고 검색할 수 있는 컨트롤러입니다.
  • cursorColor: Theme.of(context).primaryColor: 이 속성은 TextField 내에서 커서의 색상을 설정합니다. Theme.of(context).primaryColor는 현재 테마의 기본 색상을 사용하도록 설정합니다.
  • decoration: 이 속성은 TextField의 외관을 지정합니다. 위의 예시에서는 힌트 텍스트, 힌트 텍스트 스타일, 포커스될 때의 경계선 스타일 및 비활성화된 상태의 경계선 스타일을 지정하고 있습니다.
  • hintText: 'Insert Your Name': 이 속성은 TextField에 표시되는 힌트 텍스트를 지정합니다.
  • hintStyle: TextStyle(color: Colors.grey): 이 속성은 힌트 텍스트의 스타일을 지정합니다. 위의 예시에서는 회색으로 설정되었습니다.
  • focusedBorder: 이 속성은 TextField가 포커스를 받았을 때의 경계선 스타일을 지정합니다. 위의 예시에서는 검은색 경계선이 설정되었습니다.
  • enabledBorder: 이 속성은 TextField가 비활성화된 상태일 때의 경계선 스타일을 지정합니다. 위의 예시에서는 회색 경계선이 설정되었습니다.

TextEditingController 

  • TextEditingController는 주로 TextField와 사용되며, TextField 초기 값 설정, 텍스트 변경 감지, 텍스트 설정 등의 작업에 사용됩니다.
  • 또한, addListener 메서드를 사용하여 텍스트 변경을 감지하고 적절한 작업을 수행할 수 있습니다
 final TextEditingController _usernameController = TextEditingController();
  String _username = "";

  @override
  void initState() {
    super.initState();
    _usernameController.addListener(() {
      setState(() {
        _username = _usernameController.text;
      });
    });
  }
  • 먼저, _usernameController라는 TextEditingController 인스턴스를 생성합니다. 이 컨트롤러는 TextField와 연결되어 TextField에서 입력한 텍스트를 관리합니다.
  • _username이라는 문자열 변수를 선언하여 TextField에 입력된 사용자 이름을 저장합니다.
  • initState() 메서드에서 _usernameController의 addListener() 메서드를 호출하여 텍스트 변경을 감지하는 리스너를 등록합니다. 이 리스너는 TextField의 텍스트가 변경될 때마다 호출됩니다.
  • setState() 메서드 내에서 _username 변수를 업데이트하여 _usernameController의 텍스트를 가져옵니다. 이는 텍스트 필드의 값이 변경될 때마다 화면을 다시 그려주기 위해 사용됩니다.
  • 위의 코드는 StatefulWidget을 사용하는 경우 주로 사용되는 패턴 중 하나입니다. TextField에서 입력한 텍스트를 컨트롤러를 통해 가져오고, 그 값을 상태 변수에 저장하여 화면에 반영합니다. 사용자 이름을 입력받는 기능 외에도, 유효성 검사 등 다양한 로직을 구현할 수 있습니다.

TextEditingController.text 값 활용하기.

FractionallySizedBox(
  widthFactor: 1,
  child: AnimatedContainer(
    duration: const Duration(milliseconds: 200),
    padding: const EdgeInsets.symmetric(vertical: Sizes.size12),
    decoration: BoxDecoration(
      borderRadius:
          BorderRadius.circular(_username.isEmpty ? 0 : 13),
      color: _username.isEmpty
          ? Colors.grey.shade300
          : Theme.of(context).primaryColor,
      //border: Border.all(color: Theme.of(context).primaryColor)
    ),
    child: AnimatedDefaultTextStyle(
      style: TextStyle(
          color: _username.isEmpty ? Colors.grey : Colors.white,
          fontSize: Sizes.size16,
          fontWeight: FontWeight.w500),
      duration: const Duration(milliseconds: 200),
      child: Text(
        _username.isEmpty ? 'Sign Up' : 'Next',
        textAlign: TextAlign.center,
      ),
    ),
  ),
)

*_username 에 값이 있으면 하단 버튼 변하는 기능

 


같이 알아두면 유용한 것들.(중요)

  • 이메일 포멧 정규식
    - 이메일 형식이 맞는 지 정규식과 TextField의 text 값을 has.Match 함수로 판별할 수 있습니다.
    - 아래 메소드를 TextField() 의 decoration: 속성에 InputDecoration() 위젯을 넣어주고 그 안에 errorText: 로 추가해주면 에러 TextField 하단에 표시되는 에러 메세지로 활용할 수 있습니다.
 String? _isEmailValid() {
    if (_email.isEmpty) return null;
    final regExp = RegExp(
        r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+");
    //Email 정규식
    if (!regExp.hasMatch(_email)) {
      return 'Sorry, that is not a valid Email Address';
    }
    return null;
  }
  
  ...
  TextField(
  decoration: InputDecoration(
                    errorText: _isEmailValid(),
                    )
...

  • 키패드 끄기 (TextField가 아닌 다른 곳을 눌렀을 때 키패드를 사라지게 하는 방법)
    - Scaffold 부모 위젯으로 GestureDetector를 생성해줍니다.
    - 아래 소스와 같이 onTap: 에 unfocus() 가 포함된 메소드를 추가합니다.
 void _onScaffoldTap() {
    FocusScope.of(context).unfocus();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _onScaffoldTap,
...

  • onSubmitted: (키패드로 입력된 Text 제출 하기)
    사용자가 텍스트 필드에서 엔터 키를 눌렀을 때 실행되는 콜백 함수입니다. 이 콜백은 일반적으로 사용자가 입력한 텍스트를 처리하고 관련된 동작을 수행하는 데 사용됩니다. 예를 들어, 사용자가 텍스트 필드에 메시지를 입력하고 엔터 키를 누르면 해당 메시지를 전송하는 기능을 구현할 수 있습니다.
TextField(
  onSubmitted: (value) {
    // 입력된 텍스트 처리 및 동작 수행
    print('입력된 텍스트: $value');
    // ...
  },
)

 

  • onEditingComplete: (입력 종료 후, 다음 포커스로 이동했을 때 실행됨)
    사용자가 텍스트 필드의 편집을 완료했을 때 실행되는 콜백 함수입니다. 일반적으로 사용자가 다른 텍스트 필드로 이동하거나 편집을 완료한 후의 동작을 수행하는 데 사용됩니다. 예를 들어, 사용자가 사용자 이름을 입력한 후 편집을 완료하면 비밀번호 필드로 자동으로 포커스를 이동하는 기능을 구현할 수 있습니다.
TextField(
  onEditingComplete: () {
    // 편집 완료 후 동작 수행
    FocusScope.of(context).nextFocus(); // 다음 텍스트 필드로 포커스 이동
    // ...
  },
)

  • AnimatedContainer(Container에 에니메이션 효과를 주고싶을 때 사용)
    AnimatedContainer는 duration 속성에 따라 지정된 시간 동안 애니메이션 효과를 가지며, 컨테이너의 속성을 변경할 수 있는 위젯입니다. 일반적으로는 부모 위젯의 크기, 위치, 색상, 패딩 등의 속성을 변경하는 데 사용됩니다.

    [AnimatedContainer의 주요 속성]
    duration: 애니메이션의 지속 시간을 나타내는 Duration 객체입니다.
    curve: 애니메이션의 속도 곡선을 나타내는 Curve 객체로, 애니메이션 효과의 변화 속도를 조정할 수 있습니다.
    color, decoration, padding, alignment 등의 속성: 애니메이션 중에 변경될 속성들을 설정합니다.
class AnimatedContainerExample extends StatefulWidget {
  @override
  _AnimatedContainerExampleState createState() => _AnimatedContainerExampleState();
}

class _AnimatedContainerExampleState extends State<AnimatedContainerExample> {
  bool _isContainerExpanded = false;

  void _toggleContainer() {
    setState(() {
      _isContainerExpanded = !_isContainerExpanded;
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _toggleContainer,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 500),
        width: _isContainerExpanded ? 200.0 : 100.0,
        height: _isContainerExpanded ? 200.0 : 100.0,
        color: _isContainerExpanded ? Colors.blue : Colors.red,
      ),
    );
  }
}

  • AnimatedDefaultTextStyle (Text에 에니메이션 효과를 주고싶을 때 사용)
    - AnimatedDefaultTextStyle는 TextStyle 속성을 애니메이션 효과와 함께 변경할 수 있는 위젯입니다.
    주로 텍스트의 스타일, 색상, 크기 등을 변경하는 데 사용됩니다.

    [AnimatedDefaultTextStyle의 주요 속성]
    style: 애니메이션 중에 변경될 TextStyle 객체를 설정합니다.
    duration: 애니메이션의 지속 시간을 나타내는 Duration 객체입니다.
    curve: 애니메이션의 속도 곡선을 나타내는 Curve 객체로, 애니메이션 효과의 변화 속도를 조정할 수 있습니다.
class AnimatedTextStyleExample extends StatefulWidget {
  @override
  _AnimatedTextStyleExampleState createState() => _AnimatedTextStyleExampleState();
}

class _AnimatedTextStyleExampleState extends State<AnimatedTextStyleExample> {
  bool _isTextBold = false;

  void _toggleTextStyle() {
    setState(() {
      _isTextBold = !_isTextBold;
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _toggleTextStyle,
      child: AnimatedDefaultTextStyle(
        duration: const Duration(milliseconds: 500),
        style: TextStyle(
          fontSize: _isTextBold ? 24.0 : 16.0,
          fontWeight: _isTextBold ? FontWeight.bold : FontWeight.normal,
          color: _isTextBold ? Colors.blue : Colors.black,
        ),
        child: Text('Animated Text'),
      ),
    );
  }
}

 

  • prefixIcon: 입력창 앞에 아이콘 넣기
  • suffixIcon: 입력창 뒤에 아이콘 넣기
  • prefix: 입력창 앞에 위젯 넣기
  • suffix: 입력창 뒤에 위젯 넣기
TextField(
	decoration: InputDecoration(
    	suffix: Row(
      	mainAxisAlignment: MainAxisAlignment.end,
      	children: [
        FaIcon(
       	   FontAwesomeIcons.deleteLeft,
       	   color: Theme.of(context).primaryColor,
        ),
        Gaps.h10,
        const FaIcon(
          FontAwesomeIcons.eye,
          color: Colors.blue,
        )
      ],
    ),
  )
)

suffix와 Row로 아이콘 2개 뒤에 넣기


예시 출처: https://nomadcoders.co

 

반응형
Comments