如何解决react_forms 自定义小部件中的 Flutter typeahead textField 不显示所选选项文本
我正在使用 Flutter Typeahead 来使用谷歌地图位置自动完成。一切正常,只是我无法让 textField 显示所选的建议文本。我将 TextEditingController.text
设置为一些有效文本,但它在 TextField 中不显示任何内容:
viewmodel.typeAheadController.text =
suggestion.structuredFormatting.mainText;
当我在选择选项时在 TextEditingController
上设置文本值时,为什么选定的建议文本不会显示在 TextField 中?
import 'package:Flutter/material.dart';
import 'package:Flutter_riverpod/Flutter_riverpod.dart';
import 'package:Flutter_typeahead/Flutter_typeahead.dart';
import 'package:font_awesome_Flutter/font_awesome_Flutter.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:google_maps_webservice/places.dart';
import 'package:reactive_forms/reactive_forms.dart';
import 'package:Flutter/widgets.dart';
import 'package:vepo/fonts.gen.dart';
import 'package:vepo/src/domain/entities/establishment/establishment_domain_entity.dart';
import 'package:vepo/src/presentation/widgets/purely_display_widgets/text/caption_widget.dart';
import 'establishments_autocomplete_field_view_model.dart';
class VpestablishmentsAutocompleteField
extends ReactiveFormField<EstablishmentDomainEntity> {
VpestablishmentsAutocompleteField(
{@required String formControlName,this.context,this.label,this.hint,bool hasFocus = false,this.onFocusChange,Map<String,String> Function(AbstractControl<dynamic>) validationMessages,this.key})
: super(
key: key,formControlName: formControlName,validationMessages: validationMessages,showErrors: (control) => control.invalid,builder: (ReactiveFormFieldState<EstablishmentDomainEntity> field) {
final viewmodel = ProviderContainer()
.read<EstablishmentsAutocompleteFieldviewmodel>(
establishmentsAutocompleteviewmodelProvider);
return FocusScope(
child: Focus(
onFocusChange: (isFocused) {
hasFocus = isFocused;
if (onFocusChange != null) {
onFocusChange(isFocused);
}
field.setState(() {});
},child: TypeAheadFormField<Prediction>(
textFieldConfiguration: TextFieldConfiguration(
controller: viewmodel.typeAheadController,autofocus: true,decoration: Inputdecoration(
errorMaxLines: 3,suffixIconConstraints: const BoxConstraints(
minWidth: 2,minHeight: 2,),suffixIcon: ReactiveStatusListenableBuilder(
formControlName: formControlName,builder: (context,control,child) {
return control.pending
? Container(
width: 90,height: 60,child: Stack(children: [
Positioned(
top: 10,right: 15,child: CircularProgressIndicator(
backgroundColor:
Theme.of(context)
.primaryColorDark),)
]))
: Container(width: 0);
},alignLabelWithHint: true,labelStyle: TextStyle(
height: 0,fontSize: hasFocus ? 24 : 18.0,color: Theme.of(context).primaryColor),hintText: hint,labelText: label,counterText: ''),suggestionsCallback: (pattern) async {
return await viewmodel.fetchSuggestions(
pattern,context);
},suggestionsBoxdecoration: SuggestionsBoxdecoration(
elevation: 20,color: Theme.of(context).scaffoldBackgroundColor,borderRadius: const BorderRadius.all(
Radius.circular(10.0),itemBuilder: (context,suggestion) {
return ListTile(
leading: FaIcon(FontAwesomeIcons.storeAlt,size: 25,title: RichText(
text: TextSpan(
text: viewmodel.getBoldText(
suggestion.structuredFormatting.mainText,suggestion.structuredFormatting
.mainTextMatchedSubstrings.first),style: TextStyle(
fontSize: 20,fontFamily: FontFamily.hind,fontWeight: FontWeight.bold,color: Theme.of(context).primaryColorDark),children: <TextSpan>[
TextSpan(
text: suggestion
.structuredFormatting.mainText
.substring(suggestion
.structuredFormatting
.mainTextMatchedSubstrings
.first
.length as int),style: const TextStyle(
fontWeight: FontWeight.w200,color: Colors.black54))
],subtitle: VpCaption(
text:
suggestion.structuredFormatting.secondaryText,color: Colors.black54,fontSize: 17,overflow: TextOverflow.visible,);
},onSuggestionSelected: (suggestion) {
viewmodel.typeAheadController.text =
suggestion.structuredFormatting.mainText;
viewmodel.typeAheadController.value =
TextEditingValue(
text:
suggestion.structuredFormatting.mainText);
final x = EstablishmentDomainEntity(
placeId: suggestion.placeId);
field.didChange(x);
field.control.markAsTouched();
field.control.markAsDirty();
},)));
});
final Key key;
final BuildContext context;
final String label;
final String hint;
bool hasFocus;
final void Function(bool) onFocusChange;
@override
ReactiveFormFieldState<EstablishmentDomainEntity> createState() =>
ReactiveFormFieldState<EstablishmentDomainEntity>();
}
解决方法
您的 TextEditingController
是否已初始化?这段代码对我来说很好用,并且会根据选择的选项进行更新。
final TextEditingController _typeAheadController = TextEditingController();
...
Container(
width: constraints.maxWidth * 0.80,height: 50,decoration: BoxDecoration(
color: Color.fromRGBO(245,245,1),borderRadius: BorderRadius.all(Radius.circular(50))),child: Padding(
padding: EdgeInsets.only(left: 20),child: TypeAheadField(
hideOnEmpty: true,textFieldConfiguration: TextFieldConfiguration(
autofocus: false,controller: _typeAheadController,decoration: InputDecoration(
border: InputBorder.none,hintText: 'Enter your city',hintStyle: TextStyle(
fontFamily: 'Metropolis-SemiBold',color: Color.fromRGBO(197,197,1)),),suggestionsCallback: (pattern) async {
var x = await FunctionsService()
.getRegionSuggestion(pattern);
locationCodes = x[1];
suggestionList = x[0];
return x[0];
},itemBuilder: (context,suggestion) {
return ListTile(
title: Text(suggestion),);
},onSuggestionSelected: (suggestion) {
setState(() {
_typeAheadController.text = suggestion;
publicLocation = suggestion.toString();
locationSelected = true;
});
}),
,
这是一个非常具体的场景,因为我使用了很多包。
我需要为 reactive_forms 创建自定义控件值访问器,因为我的表单值是一个复杂对象 (EstablishmentDomainEntity
),而不是字符串:
import 'package:reactive_forms/reactive_forms.dart';
import 'package:vepo/src/domain/entities/establishment/establishment_domain_entity.dart';
/// Represents a control value accessor that convert between data types
/// [EstablishmentDomainEntity] and [String].
class EstablishmentValueAccessor
extends ControlValueAccessor<EstablishmentDomainEntity,String> {
@override
String modelToViewValue(EstablishmentDomainEntity modelValue) {
return modelValue == null ? '' : modelValue.name;
}
@override
EstablishmentDomainEntity viewToModelValue(String viewValue) {
return (viewValue == '' || viewValue == null)
? null
: EstablishmentDomainEntity(name: viewValue);
}
}
然后在我的自定义小部件构造函数中,我必须传入值访问器:
class VpEstablishmentsAutocompleteField
extends ReactiveFormField<EstablishmentDomainEntity> {
VpEstablishmentsAutocompleteField(
{@required String formControlName,this.key})
: super(
key: key,formControlName: formControlName,valueAccessor: EstablishmentValueAccessor(),
然后在我的 TypeAheadFormField
onSuggestionSelected
中,调用 field.didChange
并手动设置 TypeAheadFormField TextEditingController.text
:
onSuggestionSelected: (suggestion) {
viewModel.typeAheadController.text =
suggestion.structuredFormatting.mainText;
final x = EstablishmentDomainEntity(
placeId: suggestion.placeId,name: suggestion.structuredFormatting.mainText);
field.didChange(x);
},
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。