【问题标题】:Search Bar Layout with DataTable Flutter使用 DataTable Flutter 的搜索栏布局
【发布时间】:2021-05-28 18:44:14
【问题描述】:

我为我的DataTable 列表创建了一个简单的搜索栏,但问题是我不能只返回我搜索的项目,而是得到空字段和我搜索的项目。我尝试了各种方法,但我得到的错误是我需要行和列一样多,所以这是目前我让它工作的唯一方法。

但我想让它变成这样:

代码如下:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'models/vehicle.dart';
import 'services/vehicle_api.dart';
import 'models/vehicle_data_provider.dart';

class VehicleList extends StatefulWidget {
  @override
  _VehicleList createState() => _VehicleList();
}

class _VehicleList extends State<VehicleList> {
  TextEditingController controller = TextEditingController();
  String _searchResult = '';

  _getPosts() async {
    HomePageProvider provider =
        Provider.of<HomePageProvider>(context, listen: false);

    var postsResponse = await fetchVehicles();
    if (postsResponse.isSuccessful) {
      provider.setPostsList(postsResponse.data, notify: false);
    } else {
      provider.mergePostsList(
        postsResponse.data,
      );
    }

    provider.setIsHomePageProcessing(false);
  }

  @override
  void initState() {
    _getPosts();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Card(
          child: new ListTile(
            leading: new Icon(Icons.search),
            title: new TextField(
                controller: controller,
                decoration: new InputDecoration(
                    hintText: 'Search', border: InputBorder.none),
                onChanged: (value) {
                  setState(() {
                    _searchResult = value;
                  });
                }),
            trailing: new IconButton(
              icon: new Icon(Icons.cancel),
              onPressed: () {
                setState(() {
                  controller.clear();
                  _searchResult = '';
                });
              },
            ),
          ),
        ),
        Consumer<HomePageProvider>(
          builder: (context, vehicleData, child) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Container(
                  decoration: BoxDecoration(
                    color: Colors.grey[300],
                    borderRadius: BorderRadius.all(
                      Radius.circular(12.0),
                    ),
                  ),
                  child: SingleChildScrollView(
                    child: DataTable(
                      columnSpacing: 30,
                      columns: <DataColumn>[
                        DataColumn(
                          numeric: false,
                          label: Text(
                            'Friendly Name',
                            style: TextStyle(fontStyle: FontStyle.italic),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Licence Plate',
                            style: TextStyle(fontStyle: FontStyle.italic),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Delete',
                            style: TextStyle(fontStyle: FontStyle.italic),
                          ),
                        ),
                      ],
                      rows: List.generate(
                        vehicleData.postsList.length,
                        (index) {
                          VehicleData post = vehicleData.getPostByIndex(index);
                          return post.licencePlate
                                      .toLowerCase()
                                      .contains(_searchResult) ||
                                  '${post.model}'
                                      .toLowerCase()
                                      .contains(_searchResult) ||
                                  '${post.make}'
                                      .toLowerCase()
                                      .contains(_searchResult) ||
                                  post.type
                                      .toLowerCase()
                                      .contains(_searchResult)
                              ? DataRow(
                                  cells: <DataCell>[
                                    DataCell(
                                      Text('${post.friendlyName}'),
                                    ),
                                    DataCell(
                                      Text('${post.licencePlate}'),
                                    ),
                                    DataCell(
                                      IconButton(
                                        icon: Icon(Icons.delete),
                                        onPressed: () {
                                          vehicleData.deletePost(post);
                                        },
                                      ),
                                    ),
                                  ],
                                )
                              : DataRow(
/// This is the part where I return empty rows with one row with the search bar results, so I assume this must me changed
                                  cells: <DataCell>[
                                    DataCell(Text('')),
                                    DataCell(Text('')),
                                    DataCell(Text('')),
                                  ],
                                );
                        },
                      ),
                    ),
                  ),
                ),
              ],
            );
          },
        ),
      ],
    );
  }
}

似乎无法弄清楚这一点。提前感谢您的帮助!

【问题讨论】:

    标签: flutter search mobile flutter-layout


    【解决方案1】:

    好的,在你发表评论后,我终于让它像我认为你想要的那样工作。这个想法是使用两个列表而不是一个列表,并且由于该空行而不使用 List.generate 方法。当您更改 _searchResult 值时,您会使用来自 users 列表的原始值过滤 userFiltered 列表。

    我在 DataTable 中使用了 Flutter 示例并进行了这些编辑,它可以正常工作:

    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    /// This is the main application widget.
    class MyApp extends StatelessWidget {
      const MyApp({Key key}) : super(key: key);
    
      static const String _title = 'Flutter Code Sample';
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: _title,
          home: Scaffold(
            appBar: AppBar(title: const Text(_title)),
            body: MyStatelessWidget(),
          ),
        );
      }
    }
    
    
    class User{
      String name;
      int age;
      String role;
    
      User({this.name, this.age, this.role});
    }
    
    /// This is the stateless widget that the main application instantiates.
    class MyStatelessWidget extends StatefulWidget {
      MyStatelessWidget({Key key}) : super(key: key);
    
      @override
      _MyStatelessWidgetState createState() => _MyStatelessWidgetState();
    }
    
    class _MyStatelessWidgetState extends State<MyStatelessWidget> {
      List<User> users = [User(name: "Sarah", age: 19, role: "Student"), User(name: "Janine", age: 43, role: "Professor")];
      List<User> usersFiltered = [];
      TextEditingController controller = TextEditingController();
      String _searchResult = '';
    
      @override
      void initState() {
        super.initState();
        usersFiltered = users;
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Card(
              child: new ListTile(
                leading: new Icon(Icons.search),
                title: new TextField(
                    controller: controller,
                    decoration: new InputDecoration(
                        hintText: 'Search', border: InputBorder.none),
                    onChanged: (value) {
                      setState(() {
                        _searchResult = value;
                         usersFiltered = users.where((user) => user.name.contains(_searchResult) || user.role.contains(_searchResult)).toList();
                      });
                    }),
                trailing: new IconButton(
                  icon: new Icon(Icons.cancel),
                  onPressed: () {
                    setState(() {
                      controller.clear();
                      _searchResult = '';
                      usersFiltered = users;
                    });
                  },
                ),
              ),
            ),
            DataTable(
              columns: const <DataColumn>[
                DataColumn(
                  label: Text(
                    'Name',
                    style: TextStyle(fontStyle: FontStyle.italic),
                  ),
                ),
                DataColumn(
                  label: Text(
                    'Age',
                    style: TextStyle(fontStyle: FontStyle.italic),
                  ),
                ),
                DataColumn(
                  label: Text(
                    'Role',
                    style: TextStyle(fontStyle: FontStyle.italic),
                  ),
                ),
              ],
              rows: List.generate(usersFiltered.length, (index) =>
                  DataRow(
                    cells: <DataCell>[
                      DataCell(Text(usersFiltered[index].name)),
                      DataCell(Text(usersFiltered[index].age.toString())),
                      DataCell(Text(usersFiltered[index].role)),
                    ],
                  ),
              ),
            ),
          ],
        );
      }
    }
    
    

    旧帖:

    我正在寻找一种过滤数据表的方法,您的问题解决了我的问题,谢谢(我现在会尽力帮助您!)。通过使用 PaginatedDataTable 小部件而不是 DataTable 我可以实现您想要的结果。这个想法是在将列表传递给源属性之前对其进行过滤。这是我用来过滤列表的代码的一部分。在 switch 块内我过滤它以删除其他元素:

    switch(filter){
            case "Id d'expédition":
              expeditionsList = expeditionsList.where((e) => e.expeditionId.toLowerCase() == stringToSearch.toLowerCase()).toList();
              break;
          }
    
    return PaginatedDataTable(
          showCheckboxColumn: false,
          rowsPerPage: 5,
          source: DataTableSourceExpedition(
              expeditions: expeditionsList,
              onRowClicked: (index) async {
                await ExpeditionRowDialog.buildExpeditionRowDialog(
                        context, expeditionsList[index].expeditionsDetails)
                    .show();
              },
          header: Container(
            width: 100,
            child: Text("Expéditions"),
          ),
          columns: [
            DataColumn(
                label: Text("Id d'expédition"), numeric: false, tooltip: "id"),
            
          ],
        );
    

    然后我需要使用需要 DataTableSource 对象的源属性将数据传递给表。我创建了一个扩展 DataTableSource 的单独类。我将过滤后的列表作为此类的参数传递,并覆盖 DataTableSource 类的方法:

    class DataTableSourceExpedition extends DataTableSource {
        List<Expedition> expeditions = List();
        Function onRowClicked;
        Function onDeleteIconClick;
        final df = DateFormat('dd.MM.yyyy');
    
       DataTableSourceExpedition({this.expeditions, this.onRowClicked, 
          this.onDeleteIconClick});
           DataRow getRow(int index) {
           final _expedition = expeditions[index];
    
    return DataRow.byIndex(
        index: index,
        cells: <DataCell>[
          DataCell(Text("${_expedition.expeditionId}")),
          DataCell(IconButton(
            icon: Icon(Icons.delete_forever, color: kReturnColor,),
            onPressed: (){onDeleteIconClick(index);},
          ))
        ],
        onSelectChanged: (b) => onRowClicked(index));
      }
    
    
      bool get isRowCountApproximate => false;
    
    
      int get rowCount => expeditions.length;
    
    
      int get selectedRowCount => 0;
    }
    

    像这样,我可以在不需要添加空行的情况下过滤唯一的项目,如下图所示:

    如果列表为空,它也可以工作。

    【讨论】:

    • 在这种情况下我需要使用DataTable,我不确定如何传递源代码。并且不知道如何将搜索查询传递回表格,以便它只显示想要的项目..
    • 拯救了我的一天!完美而简单的数据表搜索解决方案。
    猜你喜欢
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多