Flutter中如何在AutoCompleteTextField搜索模型类数据?
解决方案
1. 修复模型类型错误
SpecialityDatum.fromJson中status字段存在类型不匹配问题,原代码用字符串默认值赋值给int类型,会导致对象初始化错误,修正如下:
factory SpecialityDatum.fromJson(Map<String, dynamic> json) => SpecialityDatum( id: json["id"]??0, speciality: json["speciality"]??"", status: json["status"]??0, // 替换原??"",匹配int类型 createdAt: json["created_at"] != null ? DateTime.parse(json["created_at"]) : null, updatedAt: json["updated_at"] != null ? DateTime.parse(json["updated_at"]) : null, deletedAt: json["deleted_at"], );
2. 转换Observable列表为普通列表
AutoCompleteTextField不直接支持ObservableList,需将数据源转换为普通列表:
suggestions: controller.specialityList.toList(),
3. 修正搜索过滤逻辑
原代码依赖对象默认toString()(返回内存地址)进行过滤,改为直接使用speciality字段匹配查询:
itemFilter: (item, query) { return item.speciality?.toLowerCase().contains(query.toLowerCase()) ?? false; },
若需严格前缀匹配,替换为startsWith即可。
4. 修正排序逻辑
基于speciality字段排序,而非对象默认toString():
itemSorter: (a, b) { return a.speciality?.compareTo(b.speciality ?? "") ?? 0; },
5. 修正选中后的文本赋值
选中建议项后,将输入框文本设置为speciality字段值:
itemSubmitted: (item) { controller.recommendedTxt.value.text = item.speciality ?? ""; },
6. 调整建议项显示内容
若仅需展示speciality字段,修改itemBuilder中的文本内容:
Text( item.speciality ?? "", // 替换原item.toStringView() style: TextStyle( fontSize: 15.sp, fontFamily: fontMulishSemiBold, color: black_1e1f20), ),
也可修改模型的toStringView方法,让它仅返回speciality:
String toStringView(){ return speciality ?? ""; }
完整修正后的AutoCompleteTextField代码
Expanded( flex:1, child: Padding( padding: const EdgeInsets.only(left: 12,top: 16,bottom: 12), child: AutoCompleteTextField( key: key, controller: controller.recommendedTxt.value, suggestions: controller.specialityList.toList(), style: TextStyle( fontFamily: fontMulishSemiBold, fontSize: 15.sp, color: black_1e1f20), decoration: InputDecoration( focusedBorder: InputBorder.none, border: InputBorder.none, contentPadding: EdgeInsets.zero, isDense: true, hintText: str_search, hintStyle: TextStyle( color: silver_9393aa, fontSize: 15.sp, fontFamily: fontMulishSemiBold ), prefixIconConstraints: const BoxConstraints( maxHeight: 24, maxWidth: 24, ), prefixIcon: Padding( padding: const EdgeInsets.only(bottom: 5,right: 5), child: SvgPicture.asset( icon_search, color: silver_9393aa, ), ), ), itemFilter: (item, query) { return item.speciality?.toLowerCase().contains(query.toLowerCase()) ?? false; }, itemSorter: (a, b) { return a.speciality?.compareTo(b.speciality ?? "") ?? 0; }, itemSubmitted: (item) { controller.recommendedTxt.value.text = item.speciality ?? ""; }, itemBuilder: (context, item) { return Container( padding: EdgeInsets.only(left: 16.w,right: 16.w,top: 20.h), width: double.infinity, decoration: BoxDecoration( color: light_green_f8fbff, borderRadius: BorderRadius.circular(8), ), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.speciality ?? "", style: TextStyle( fontSize: 15.sp, fontFamily: fontMulishSemiBold, color: black_1e1f20), ), SizedBox(height: 19.5.h,), const Line() ], ), ); }, ), ), ),
内容的提问来源于stack exchange,提问作者Vrusti Patel
相关产品推荐
相关产品推荐

