Flutter: ввод текста
За ввод текста во Flutter отвечает виджет TextField и соответствующий класс TextEditingController для управления вводом текста
Для примера отрисуем страницу авторизации. Сначала «Рыба»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import 'package:flutter/material.dart'; import 'package:invent/globals.dart' as globals; class Login extends StatefulWidget { _LoginState createState() => _LoginState(); // сюда передаем текущее состояние страницы } class _LoginState extends State<Login> {// _ впереди класса, означает чтоб скрыть доступ из другх файлов @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Авторизация')), body: Center( ), ); } } |
Добавим надписи Логин и Пароль:
1 2 3 4 5 6 7 8 9 10 11 12 |
body: Center( child: Padding( padding: EdgeInsetsDirectional.fromSTEB(10, 10, 10, 0), child: Column( children: [ Text('Логин:'), Text('Пароль:',), ], ), ), ), |
Далее необходимо рассказать о классе TextEditingController.
Данный класс имеет два конструктора:
TextEditingController({String text})
TextEditingController.fromValue(TextEditingValue value)
Первый конструктор в качестве параметра принимает начальное значение, которое затем будет отображаться в ассоциированном текстовом поле. Второй конструктор также принимает начальное значение, но в виде объекта TextEditingValue
TextEditingController позволяет контроллировать введенный и выделенный текст в поле ввода, для чего у него определены три свойства:
- selection: выделенный текст в виде объекта TextSelection
- text: текущий введенный текст в виде объекта String
- value: текущее значение в виде объекта TextEditingValue
При изменении ввода в текстовом поле связанный объект TextEditingController
уведомляет слушателей об изменении. Для добавления слушателей — функций обработного вызова в классе определен метод addListener()
. Все добавленные слушатели могут считать введенный текст, а также выделенный текст и таким образом узнать о произошедших изменениях.
Когда объект TextEditingController больше не нужен, у него надо вызвать метод dispose()
. Это позволит освободить все ресурсы, используемые объектом.
Таким образом модифицируем код, добавив поля ввода для логина и пароля:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class _LoginState extends State<Login> {// _ впереди класса, означает чтоб скрыть доступ из другх файлов final _controller1 = TextEditingController(); final _controller2 = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Авторизация')), body: Center( child: Padding( padding: EdgeInsetsDirectional.fromSTEB(10, 10, 10, 0), child: Column( children: [ Text('Логин:'), TextField( style: TextStyle(fontSize: 22), controller: _controller1 ), Text('Пароль:',), TextField( style: TextStyle(fontSize: 22), controller: _controller2 ), ], ), ), ), ); } } |
Теперь создадим обработчики событий ввода и начальное заполнение контроллеров.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class _LoginState extends State<Login> {// _ впереди класса, означает чтоб скрыть доступ из другх файлов final _controller1 = TextEditingController(); final _controller2 = TextEditingController(); _changField(){ print("-чтото повводили.."); } @override void initState() { super.initState(); _controller1.text = "Логин"; _controller1.addListener(_changField); _controller2.text = "***"; _controller2.addListener(_changField); } @override void dispose() { _controller1.dispose(); _controller2.dispose(); super.dispose(); } |
Результат:
Если поля ввода заполняются например из списка, то заполнение начальных значений и их сохранение можно организовать как-то так:
1 2 3 4 5 6 7 |
TextField( style: TextStyle(fontSize: 22), controller: TextEditingController()..text = globals.ComfortList[index]["temp"].toString(), onChanged: (text) { globals.ComfortList[index]["temp"]=text; print("Введено: {$index},{$text}"); } |
Получится: