Панель поиска не работала должным образом в таблице draggablescrollesheet (Флаттер)

#flutter

Вопрос:

Я новичок в Флаттере. У меня возникли проблемы с моей собственной панелью поиска на перетаскиваемом нижнем листе. Я создал перетаскиваемый нижний лист для поиска информации при нажатии на поле поиска на главном экране. Я добавил панель поиска и представление списка на листе, но панель поиска работала неправильно. Он не мог мгновенно отфильтровать данные, он просто показывал результаты при закрытии клавиатуры. Кто-нибудь, помогите мне, пожалуйста.

 class AddPersonalInfo extends StatefulWidget {  final String mail, password;  const AddPersonalInfo({Key? key, required this.mail, required this.password})  : super(key: key);   @override  _AddPersonalInfoState createState() =gt; _AddPersonalInfoState(); }  class _AddPersonalInfoState extends Statelt;AddPersonalInfogt; {  TextEditingController _search = TextEditingController();   Listlt;Citygt; cites = [  City(id: 1, code: "HN", name: "Ha Noi"),  City(id: 2, code: "HCM", name: "Ho CHi Minh"),  City(id: 3, code: "DN", name: "Da Nang"),  City(id: 4, code: "HP", name: "Hai Phong"),  City(id: 5, code: "CT", name: "Can Tho"),  City(id: 6, code: "DNN", name: "Dong Nai"),  City(id: 7, code: "KH", name: "Khanh Hoa"),  City(id: 8, code: "PY", name: "Phu Yen"),  City(id: 9, code: "NT", name: "Nha Trang"),  City(id: 10, code: "VL", name: "Vinh Long"),  City(id: 11, code: "HD", name: "Hai Duong"),  City(id: 12, code: "BD", name: "Binh Duong")  ];   City? selected;   Listlt;Citygt; foundCity = [];   @override  void initState() {  super.initState();   setState(() {  foundCity = cites;  });  }   @override  Widget build(BuildContext context) {  Size screenSize = MediaQuery.of(context).size;  Orientation orientation = MediaQuery.of(context).orientation;   return GestureDetector(  onTap: () {  FocusScope.of(context).unfocus();  },  child: Scaffold(  backgroundColor: Colors.white,  body: SafeArea(  child: LayoutBuilder(builder: (context, snapshot) {  if (snapshot.maxWidth lt;= screenSize.width amp;amp;  orientation == Orientation.portrait) {  return SingleChildScrollView(  scrollDirection: Axis.vertical,  child: Container(  padding: EdgeInsets.fromLTRB(30 * screenScale(context), 0,  30 * screenScale(context), 0),  child: Column(  crossAxisAlignment: CrossAxisAlignment.center,  children: [  Stack(  children: [  Container(  alignment: Alignment.topCenter,  padding: EdgeInsets.only(  bottom: 20 * screenScale(context)),  child: introText("Create account", context),  ),  backBtn(context),  ],  ),  mainText(  "Let's create an account to grab all latest gadgets and enjoy the best experiences.",  context),  Row(  mainAxisAlignment: MainAxisAlignment.spaceBetween,  crossAxisAlignment: CrossAxisAlignment.start,  children: [_fnameField(), _lnameField()],  ),  _phoneField(),  GestureDetector(  onTap: () =gt; showModalBottomSheet(  backgroundColor: Colors.transparent,  isScrollControlled: true,  context: context,  builder: (context) =gt; buildSheet(),  ),  child: Container(  height: 50,  margin: EdgeInsets.only(top: 15),  padding: EdgeInsets.only(left: 10, right: 7),  decoration: BoxDecoration(  border: Border.all(color: Colors.grey),  borderRadius: BorderRadius.circular(7),  ),  child: Row(  mainAxisAlignment: MainAxisAlignment.spaceBetween,  children: [  selected == null  ? Text("Select city",  style: TextStyle(  fontSize: 16,  color: Colors.grey.shade700))  : Text("${selected!.name}",  style: TextStyle(  fontSize: 16, color: Colors.black)),  Icon(Ionicons.chevron_down_outline, size: 24)  ],  ),  ),  )  ],  ),  ),  );  } else {  return SingleChildScrollView(  scrollDirection: Axis.vertical,  child: Container(  padding: EdgeInsets.fromLTRB(30 * screenScale(context), 0,  30 * screenScale(context), 0),  child: Column(  crossAxisAlignment: CrossAxisAlignment.center,  children: [],  ),  ),  );  }  }),  ),  ),  );  }   Widget buildSheet() {  return GestureDetector(  behavior: HitTestBehavior.opaque,  onTap: () {  Navigator.of(context).pop();  },  child: DraggableScrollableSheet(  initialChildSize: 0.9,  builder: (_, controller) =gt; Container(  padding: EdgeInsets.fromLTRB(10, 10, 10, 0),  decoration: BoxDecoration(  color: Colors.white,  borderRadius: BorderRadius.vertical(  top: Radius.circular(20),  ),  ),  child: Column(  children: [  Divider(  thickness: 4,  color: Colors.grey.shade300,  endIndent: 170,  indent: 170,  ),  Padding(  padding: EdgeInsets.only(bottom: 15, top: 5),  child: Text("Select city",  style: TextStyle(  fontSize: 18,  color: Colors.black,  fontWeight: FontWeight.bold)),  ),  Padding(  padding: EdgeInsets.only(bottom: 10),  child: TextFormField(  controller: _search,  keyboardType: TextInputType.name,  style: TextStyle(fontSize: 16 * fontScale(context)),  decoration: InputDecoration(  border: OutlineInputBorder(  borderRadius:  BorderRadius.circular(7 * screenScale(context))),  contentPadding:  EdgeInsets.only(top: 10 * screenScale(context)),  hintText: 'Search',  prefixIcon: Icon(Ionicons.search_outline),  ),  onChanged: (value) {  setState(() {  foundCity = cites  .where(  (city) =gt; city.name.toLowerCase().contains(value))  .toList();  });  },  ),  ),  Expanded(  child: foundCity.length gt; 0  ? ListView.builder(  itemCount: foundCity.length,  itemBuilder: (context, index) {  final city = foundCity[index];  return ListTile(  title: Text(city.name),  onTap: () {  Navigator.of(context).pop();  setState(() {  selected = city;  });  },  );  },  )  : Padding(  padding: EdgeInsets.only(top: 50),  child: Text(  "No data.",  style: TextStyle(fontSize: 16),  ),  ),  ),  ],  ),  ),  ),  );  } }  

Ответ №1:

Хорошо, я проверил ваш код, и, похоже, вы упустили небольшую проблему, когда вы создаете showModalBottomSheet, он больше не является частью вашего виджета с отслеживанием состояния

Я настроил код так, чтобы он работал сейчас:

 Widget buildSheet(BuildContext context) {  return StatefulBuilder(builder: (BuildContext context, setState) {  return GestureDetector(  behavior: HitTestBehavior.opaque,  onTap: () {  Navigator.of(context).pop();  },  child: DraggableScrollableSheet(  initialChildSize: 0.9,  builder: (_, controller) =gt; Container(  padding: EdgeInsets.fromLTRB(10, 10, 10, 0),  decoration: BoxDecoration(  color: Colors.white,  borderRadius: BorderRadius.vertical(  top: Radius.circular(20),  ),  ),  child: Column(  children: [  Divider(  thickness: 4,  color: Colors.grey.shade300,  endIndent: 170,  indent: 170,  ),  Padding(  padding: EdgeInsets.only(bottom: 15, top: 5),  child: Text("Select city",  style: TextStyle(  fontSize: 18,  color: Colors.black,  fontWeight: FontWeight.bold)),  ),  Padding(  padding: EdgeInsets.only(bottom: 10),  child: TextFormField(  controller: _search,  keyboardType: TextInputType.name,  style: TextStyle(fontSize: 16),  decoration: InputDecoration(  border: OutlineInputBorder(  borderRadius: BorderRadius.circular(7)),  contentPadding: EdgeInsets.only(top: 10),  hintText: 'Search',  prefixIcon: Icon(Icons.access_alarm),  ),  onChanged: (value) {  setState(() {  foundCity = cites  .where((city) =gt;  city.name!.toLowerCase().contains(value))  .toList();  });  },  ),  ),  Expanded(  child: foundCity.isNotEmpty  ? ListView.builder(  itemCount: foundCity.length,  itemBuilder: (context, index) {  final city = foundCity[index];  return ListTile(  title: Text(city.name!),  onTap: () {  Navigator.of(context).pop();  setState(() {  selected = city;  });  },  );  },  )  : Padding(  padding: EdgeInsets.only(top: 50),  child: Text(  "No data.",  style: TextStyle(fontSize: 16),  ),  ),  ),  ],  ),  ),  ),  );  });  }  

Комментарии:

1. но есть еще одна проблема, я не могу выбрать город без поиска, как раньше, я просто могу выбирать, когда что-то ищется или открывается клавиатура. Надеюсь, ты это исправишь.

2. Хорошо, я не уверен, что это правильный ответ, но вот что вы можете сделать: добавьте контроллер focusNode для своего текстового поля и вызовите его (_focus.requestFocus ()), прежде чем создавать свой список. Это активирует состояние.

3. Большое вам спасибо @WBG. Я уже исправил это, просто добавьте оператор «this.setState (() {})», чтобы вызвать состояние родительского экрана.