如何将值从SearchBar传递到Flutter中的上一个屏幕

时间:2020-10-09 20:46:44

标签: flutter dart

我有一个屏幕,其中有一个TextFormField。当我单击此TextFormField时,我将打开一个包含项目的SearchBar。 是否可以通过某种方式将从SearchBar中选择的值传递到上一个屏幕? 我希望在单击某个项目以关闭SearchBar并在上一个屏幕上(在MyHomePage上显示该项目的名称时,是否可以)。 这是我的进度,但是我不知道如何将值反向传递:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Search Bar Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  String _vehicleReg = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: buildAppBar(),
      body: buildUI(context),
    );
  }

  Widget buildAppBar() {
    return AppBar(title: Text('Search Reg Number'));
  }

  Widget buildUI(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        _buildVehicleRegTxtField(context),
        SizedBox(height: 200),
        selectedVehicle(),
      ],
    );
  }

  Widget selectedVehicle() {
    return Container(
      child: Text(
        'Selected vehicle will be displayed here.',
      ),
    );
  }

  Widget _buildVehicleRegTxtField(BuildContext context) {
    return TextFormField(
      onSaved: (val) {
        _vehicleReg = val;
      },
      readOnly: true,
      onTap: () {
        showSearch(context: context, delegate: PlateItemsSearch());
      },
      style: TextStyle(
        color: Colors.blue,
        fontFamily: 'OpenSans',
        fontSize: 24,
      ),
      decoration: InputDecoration(
        border: InputBorder.none,
        hintText: 'Click for Vehicles',
      ),
    );
  }
}

class PlateItemsSearch extends SearchDelegate<PlateNumber> {
  String selectedPlateNumber = "";

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          icon: Icon(Icons.clear),
          onPressed: () {
            query = "";
          })
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildResults(BuildContext context) {
    return Center(
      child: Text(
        selectedPlateNumber,
        style: TextStyle(fontSize: 20),
      ),
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final myPlatesList = query.isEmpty
        ? loadPlateNumbers()
        : loadPlateNumbers().where((plate) {
            return plate.regNumber.contains(query);
          }).toList();
    return myPlatesList.isEmpty
        ? Text(
            'Plate Not Found',
            style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
          )
        : ListView.builder(
            itemCount: myPlatesList.length,
            itemBuilder: (context, index) {
              final PlateNumber plateNumber = myPlatesList[index];
              return ListTile(
                leading: Icon(Icons.directions_car),
                onTap: () {
                  showResults(context);
                  selectedPlateNumber = plateNumber.regNumber;
                },
                title: RichText(
                  text: TextSpan(
                    text: plateNumber.regNumber.substring(0, query.length),
                    style: TextStyle(
                        fontSize: 20,
                        color: Colors.black,
                        fontWeight: FontWeight.bold),
                    children: [
                      TextSpan(
                        text: plateNumber.regNumber.substring(query.length),
                        style: TextStyle(fontSize: 20, color: Colors.grey),
                      )
                    ],
                  ),
                ),
              );
            },
          );
  }
}

class PlateNumber {
  final int id;
  final String regNumber;

  PlateNumber({this.id, this.regNumber});
}

List<PlateNumber> loadPlateNumbers() {
  var pn = <PlateNumber>[
    PlateNumber(id: 1, regNumber: 'DE99ABC'),
    PlateNumber(id: 2, regNumber: 'AB22SDK'),
    PlateNumber(id: 3, regNumber: 'KS88ASD'),
    PlateNumber(id: 4, regNumber: 'NV37SSD'),
    PlateNumber(id: 5, regNumber: 'PT20KLK'),
    PlateNumber(id: 6, regNumber: 'TEST123'),
    PlateNumber(id: 7, regNumber: 'VT20QWE'),
    PlateNumber(id: 13, regNumber: 'JS23POP'),
    PlateNumber(id: 14, regNumber: 'XX12WWW'),
    PlateNumber(id: 15, regNumber: 'AB01RCA')
  ];
  return pn;
}

感谢阅读!

2 个答案:

答案 0 :(得分:1)

从搜索页面中选择项目后,我将“ MyHomePage”小部件从“无状态”更改为“有状态”以刷新页面。
并在选择ListTile的项目时添加,调用“关闭”并返回值。

close(context, plateNumber);

这是您想要的完整代码。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Search Bar Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  String _vehicleReg = "";
  PlateNumber selectedPlatItem;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: buildAppBar(),
      body: buildUI(context),
    );
  }

  Widget buildAppBar() {
    return AppBar(title: Text('Search Reg Number'));
  }

  Widget buildUI(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        _buildVehicleRegTxtField(context),
        SizedBox(height: 200),
        selectedVehicle(),
      ],
    );
  }

  Widget selectedVehicle() {
    return Container(
      child: Text(
        selectedPlatItem == null
            ? 'Selected vehicle will be displayed here.'
            : selectedPlatItem.regNumber,
      ),
    );
  }

  Widget _buildVehicleRegTxtField(BuildContext context) {
    return TextFormField(
      onSaved: (val) {
        _vehicleReg = val;
      },
      initialValue: selectedPlatItem?.regNumber,
      readOnly: true,
      onTap: () async {
        selectedPlatItem =
            await showSearch(context: context, delegate: PlateItemsSearch());
        print(selectedPlatItem);
        setState(() {});
      },
      style: TextStyle(
        color: Colors.blue,
        fontFamily: 'OpenSans',
        fontSize: 24,
      ),
      decoration: InputDecoration(
        border: InputBorder.none,
        hintText: 'Click for Vehicles',
      ),
    );
  }
}

class PlateItemsSearch extends SearchDelegate<PlateNumber> {
  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          icon: Icon(Icons.clear),
          onPressed: () {
            query = "";
          })
    ];
  }

  @override
  Widget buildResults(BuildContext context) {
    return Container();
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final myPlatesList = query.isEmpty
        ? loadPlateNumbers()
        : loadPlateNumbers().where((plate) {
            return plate.regNumber.contains(query);
          }).toList();
    return myPlatesList.isEmpty
        ? Text(
            'Plate Not Found',
            style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
          )
        : ListView.builder(
            itemCount: myPlatesList.length,
            itemBuilder: (context, index) {
              final PlateNumber plateNumber = myPlatesList[index];
              return ListTile(
                leading: Icon(Icons.directions_car),
                onTap: () {
                  showResults(context);
                  close(context, plateNumber);
                },
                title: RichText(
                  text: TextSpan(
                    text: plateNumber.regNumber.substring(0, query.length),
                    style: TextStyle(
                        fontSize: 20,
                        color: Colors.black,
                        fontWeight: FontWeight.bold),
                    children: [
                      TextSpan(
                        text: plateNumber.regNumber.substring(query.length),
                        style: TextStyle(fontSize: 20, color: Colors.grey),
                      )
                    ],
                  ),
                ),
              );
            },
          );
  }
}

class PlateNumber {
  final int id;
  final String regNumber;

  PlateNumber({this.id, this.regNumber});
}

List<PlateNumber> loadPlateNumbers() {
  var pn = <PlateNumber>[
    PlateNumber(id: 1, regNumber: 'DE99ABC'),
    PlateNumber(id: 2, regNumber: 'AB22SDK'),
    PlateNumber(id: 3, regNumber: 'KS88ASD'),
    PlateNumber(id: 4, regNumber: 'NV37SSD'),
    PlateNumber(id: 5, regNumber: 'PT20KLK'),
    PlateNumber(id: 6, regNumber: 'TEST123'),
    PlateNumber(id: 7, regNumber: 'VT20QWE'),
    PlateNumber(id: 13, regNumber: 'JS23POP'),
    PlateNumber(id: 14, regNumber: 'XX12WWW'),
    PlateNumber(id: 15, regNumber: 'AB01RCA')
  ];
  return pn;
}


  [1]: https://i.stack.imgur.com/EtsuA.gif

答案 1 :(得分:0)

使用状态管理方法(例如提供程序或其他方法)会更好,但是您可以通过以下方式将其作为类构造函数传递:

在MyHomePage中:

class MyHomePage extends StatelessWidget {
  final String value;

  const MyHomePage({Key key, this.value}) : super(key: key);

在PlateItemsSearch中,可能在后退按钮中:

Navigator.of(context).pop(MyHomePage(value : theValueYouWantToPass ));