应该将 Bloc 模式用于颤动文本字段,如果是的话如何?

Posted

技术标签:

【中文标题】应该将 Bloc 模式用于颤动文本字段,如果是的话如何?【英文标题】:should Bloc pattern be used for flutter textfield and if yes how? 【发布时间】:2020-10-14 09:42:21 【问题描述】:

所以我是 Bloc 的新手,但我从以前从事原生 android 开发的工作中了解它是如何工作的,但我想了解的是是否应该实现它来创建类似 TextField 的东西。现在,请记住,我正在尝试多次重用此 TextField,并且我希望 bloc 模式动态验证输入,但我是否应该完全实现它就像处理用户输入的文本一样? p>

我所做的是我为文本字段创建了一个简单的块模式来处理用户输入,但它不会不时保存值它会覆盖以前的值并且光标会继续移动到正文的开头

import 'dart:math';

import 'package:competitionapp/data_model/events/formTextFieldEvent.dart';
import 'package:competitionapp/data_model/states/formTextFieldState.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

FormTextFieldBloc bloc = FormTextFieldBloc();

class FormTextFieldBloc extends Bloc<FormTextFieldEvent, FormTextFieldState> 
  void onChanged(String value) 
    if (value == null || value.isEmpty)
//      todo change to handle errors
      this.add(TextChangedEvent("error"));
    else
      this.add(TextChangedEvent(value));
  

  @override
  FormTextFieldState get initialState => FormTextFieldState.initState();

  @override
  Stream<FormTextFieldState> mapEventToState(FormTextFieldEvent event) async* 
    if (event is TextChangedEvent) 
      print("value received: $event.eventText");
      yield FormTextFieldState(event.eventText);
    
  


import 'package:competitionapp/data_model/blocModels/formTextFieldBloc.dart';
import 'package:competitionapp/data_model/states/formTextFieldState.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

// ignore: must_be_immutable
class FormTextField extends StatelessWidget 
  final TextEditingController _controller;
  final String hint;
  final IconData iconData;
  final TextInputType inputType;

  final int maxLines;
  final int maxLength;
  final EdgeInsetsGeometry padding;
  final FormTextFieldBloc formTextFieldBloc;

  FormTextField(this._controller, this.formTextFieldBloc,
      this.hint,
      this.iconData,
      this.inputType: TextInputType.text,
      this.maxLines: 1,
      this.maxLength,
      this.padding: const EdgeInsets.fromLTRB(15, 5, 15, 5));

  @override
  Widget build(BuildContext context) 
    return Padding(
      padding: padding,
      child: BlocBuilder(
        bloc: formTextFieldBloc,
        builder: (context, FormTextFieldState state) 
          if (state.text.isNotEmpty && state.text != null) 
            _controller.text = state.text;
            print("state text: $state.text");
          
          return TextField(
            onChanged: (value) 
              print(value);
              formTextFieldBloc.onChanged(_controller.text);
            ,
            onEditingComplete: ()
              print(_controller.text);
            ,
            maxLength: maxLength ?? maxLength,
            maxLines: maxLines,
            keyboardType: inputType,
            controller: _controller,
            decoration: InputDecoration(
              contentPadding: EdgeInsets.symmetric(vertical: 10),
              border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(10),
                  borderSide: BorderSide(color: Colors.transparent, width: 0)),
              focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(10),
                  borderSide: BorderSide(color: Colors.transparent, width: 0)),
              enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(10),
                  borderSide: BorderSide(color: Colors.transparent, width: 0)),
              hintText: hint,
              hintStyle:
                  Theme.of(context).textTheme.caption.copyWith(fontSize: 18),
              filled: true,
              fillColor: Theme.of(context).cardColor,
              prefixIcon: Icon(
                iconData,
                size: 16,
                color: Theme.of(context).hintColor,
              ),
            ),
          );
        ,
      ),
    );
  


【问题讨论】:

你试过使用provider吗?它比 bloc 更简单,而且工作正常,不过,这完全取决于您的选择。 您的意思是集团供应商吗?或状态管理中的提供者 状态管理一 here 就是一个例子。 【参考方案1】:

这里出现问题是因为 TextField 上的值始终在 _controller.text = state.text; 上被覆盖,并在 onChanged() 上不断更新。解决此问题的一种方法是仅在提交条目时更新 TextField 值,即在onFieldSubmitted()

您可以检查类似的方法here。虽然它不使用 Stream 来监听变化,但 TextField 值需要更新为所需的格式。

【讨论】:

以上是关于应该将 Bloc 模式用于颤动文本字段,如果是的话如何?的主要内容,如果未能解决你的问题,请参考以下文章

如何在颤动中使用 Bloc 模式处理用户注册错误

如何将 bloc 模式与颤振应用程序集成?

如何减少颤动中Textfield的额外填充

为啥 AnimatedList 在颤动中不使用 bloc 状态的列表构建?

在颤动中使用块和下拉菜单

如何在颤动中将焦点转移到另一个文本表单字段