TextField 的键盘突然消失

Keyboard suddenly disappears of TextField

我创建了一个页面,其中有搜索栏,然后是列表视图生成器,它正在构建来自提供商 class 的列表项。当我点击搜索栏时,键盘出现,突然消失,页面刷新。刷新页面时,首先显示 circularprogressIndicator,然后显示常规 ListView.builder请帮助。 提前致谢!

import 'package:carstraders/models/cars.dart';
import 'package:carstraders/providers/cars_provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class SearchPage extends StatefulWidget {
  static const routeName = 'search-page';

  const SearchPage({Key? key}) : super(key: key);

  @override
  _SearchPageState createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  var search = TextEditingController();
  var list = [];
  List<Cars> allItems = [];
  String query = '';

  bool isFirstTime = true;

  @override
  void initState() {
    allItems = Provider.of<CarsProvider>(context, listen: false).list;
    list = allItems;
    // TODO: implement initState
    super.initState();
  }

这是搜索项目和更新列表的函数

  void searchItem(String val) {
    final searched = allItems.where((element) {
      final transmission = element.transmission.toLowerCase();
      final model = element.model.toLowerCase();
      final make = element.make.toLowerCase();
      final price = element.price.toString();
      final engine = element.engine.toString();
      final searchedVal = val.toLowerCase();
      if (model.contains(searchedVal) ||
          make.contains(searchedVal) ||
          price.contains(searchedVal) ||
          engine.contains(searchedVal) ||
          transmission.contains(searchedVal)) {
        return true;
      }
      return false;
    }).toList();
    setState(() {
      list = searched;
      query = val;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Search'),
      ),
      body: FutureBuilder(
        future: Provider.of<CarsProvider>(context,listen: false).fetchAndSet(),
        builder: (ctx, snap) => snap.connectionState == ConnectionState.waiting
            ? const Center(
                child: CircularProgressIndicator(),
              )
            : Column(children: [
                Row(
                  children: [
                    Expanded(
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: TextField(
                          onChanged: searchItem,
                          // style: TextStyle(color: Colors.white),
                          controller: search,
                          key: const Key('search'),
                          keyboardType: TextInputType.emailAddress,
                          decoration: InputDecoration(
                            label: const Text('Search'),
                            suffixIcon: query.isEmpty
                                ? null
                                : GestureDetector(
                                    child: const Icon(Icons.close),
                                    onTap: () {
                                      setState(() {
                                        query = '';
                                        searchItem('');
                                        search.clear();
                                        FocusScope.of(context).unfocus();
                                      });
                                    },
                                  ),
                            prefixIcon: const Icon(Icons.search_sharp),
                            enabledBorder: const OutlineInputBorder(
                              borderSide: BorderSide(
                                color: Colors.grey,
                                width: 0.5,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                Expanded(
                  child: ListView.builder(
                    itemBuilder: (ctx, i) => buildItem(list[i], context),
                    itemCount: list.length,
                  ),
                )
              ]),
      ),
    );
  }
}

此小部件构建 listview.builder

的项目
Widget buildItem(Cars item, BuildContext context) {
  return GestureDetector(
    onTap: () =>
        Navigator.of(context).pushNamed('search-item-detail', arguments: item),
    child: Card(
      elevation: 5,
      child: Row(
        // mainAxisAlignment: MainAxisAlignment.start,
        children: [
          SizedBox(
            width: MediaQuery.of(context).size.width * 0.43,
            child: Image.network(item.img),
          ),
          SizedBox(width: MediaQuery.of(context).size.width * 0.02),
          Column(
            children: [
              Text(
                item.year.toString() + ' ' + item.make + ' ' + item.model,
                style: const TextStyle(
                  color: Colors.blueAccent,
                ),
              ),
              SizedBox(
                  width: MediaQuery.of(context).size.width * 0.5,
                  child: const Divider(color: Colors.black)),
              Row(
                children: [
                  Text('${item.mileage} mi'),
                  Container(
                      margin: EdgeInsets.symmetric(
                          horizontal: MediaQuery.of(context).size.width * 0.03),
                      decoration: const BoxDecoration(
                          border: Border(left: BorderSide(color: Colors.grey))),
                      child: const Text('')),
                  Text('£${item.price}')
                ],
              ),
              SizedBox(
                  width: MediaQuery.of(context).size.width * 0.5,
                  child: const Divider(color: Colors.black)),
              Row(
                children: [
                  Text('   ' + item.plateNo),
                  Container(
                    margin: EdgeInsets.symmetric(
                        horizontal: MediaQuery.of(context).size.width * 0.03),
                    child: const Text(''),
                    decoration: const BoxDecoration(
                        border: Border(left: BorderSide(color: Colors.grey))),
                  ),
                  Text(item.transmission)
                ],
              )
            ],
          )
        ],
      ),
    ),
  );
}

未来的构建器在每次构建时触发。因此,当您单击 searchBox 时,键盘会更改屏幕大小并 Expanded 重建 futureBuilder


解决方法简单。

替换下面部分未来的Builder

Column
  row
  Expanded
    listView.Builder

ListView.builder(
   itemBuilder: (ctx, i) {
    if(i==0){
      return row  
    }
    return buildItem(list[i -1], context)

   },
   itemCount: list.length + 1,
),
 

我觉得你的代码可以写的更好。如果您使用 bloc 模式或 Riverpod 模式(类似于提供者并且具有相同的作者) 所以请看这个链接