简体   繁体   中英

How Create SearchView in List Flutter

i need yur advice. I Have code to fetch data from api to ListView.

The question is, how to create searchview in this listview.

class PM extends StatefulWidget {
  @override
  _PMState createState() => _PMState();
}

class _PMState extends State<PM> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  void showInSnackBar(String value) {
    _scaffoldKey.currentState.showSnackBar(new SnackBar(
      content: new Text(value),
      backgroundColor: Colors.blueAccent,
    ));
  }

  final GlobalKey<RefreshIndicatorState> _refresh =
      GlobalKey<RefreshIndicatorState>();

  ModelPM modelPM;
  ModelPM _modelPM;

  bool loading = false;

  Future<Null> _fetchData() async {
    setState(() => loading = true);
    var value;

    SharedPreferences preferences = await SharedPreferences.getInstance();
    setState(() {
      value = preferences.getString("id");
    });

    final response = await http.post(BaseURL.systemTicket, body: {
      "key": BaseURL.apiKey,
      "method": "get",
      "resource": "tabel_pm",
      "filters[adminidtabelpm]": value,
    });

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      final pmModelFromJson = ModelPM.fromJson(data);

      setState(() {
        modelPM = pmModelFromJson;
        loading = false;
      });
    } else {
      showInSnackBar("Data Gagal Load");
    }
  }

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

  _listPM(i) {
    final x = modelPM.results[i];
    return Card(
      elevation: 8.0,
      margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
      child: ListTile(
        onTap: () {
          Navigator.of(context).push(
              MaterialPageRoute(builder: (context) => DetilPM(x, _fetchData)));
        },
        contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),


        title: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              x.name,
              textAlign: TextAlign.start,
              style: TextStyle(
                  fontSize: 12,
                  color: x.status == "Not Yet"
                      ? Colors.blue
                      : x.status == "Pending" ? Colors.red : Colors.green,
                  fontWeight: FontWeight.bold),
            ),
            Text(
              'Status : ' + x.status,
              textAlign: TextAlign.start,
              style: TextStyle(
                  fontSize: 12,
                  color: x.status == "Not Yet"
                      ? Colors.blue
                      : x.status == "Pending" ? Colors.red : Colors.green,
                  fontWeight: FontWeight.bold),
            ),
            SizedBox(
              height: 10,
            ),
          ],
        ),

        subtitle: Column(
          children: <Widget>[
            Row(
              children: <Widget>[
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text("MIDTID",
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text("TID",
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text("CSI",
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
              ],
            ),
            Row(
              children: <Widget>[
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text(x.midtid,
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text(x.tid,
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text(x.csi,
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
              ],
            )
          ],
        ),
        trailing:
            Icon(Icons.keyboard_arrow_right, color: Colors.black, size: 30.0),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PM CIMB List'),
      ),
      key: _scaffoldKey,

      body: RefreshIndicator(
        onRefresh: _fetchData,
        key: _refresh,
        child: loading
            ? Center(child: CircularProgressIndicator())
            : ListView.builder(
                itemCount: modelPM.results.length,
                itemBuilder: (context, i) {
                  return _listPM(i);
                },
              ),
      ),
    );
  }
}

and below this model class PM.

class ModelPM {
  final int status;
  final String status_message;
  final List<ModelPMResult> results;

  ModelPM({this.status, this.status_message, this.results});
  factory ModelPM.fromJson(Map<String, dynamic> json) {
    List<ModelPMResult> results = (json['result'] as List)
        .map((resultTicketJson) => ModelPMResult.fromJson(resultTicketJson))
        .toList();

    return ModelPM(
      status: json['status'],
      status_message: json['status_message'],
      results: results,
    );
  }
}

class ModelPMResult {
  final String id;
  final String admintabelpm;
  final String namaitfs;
  final String serial;
  final String merchantid;
  final String assetid;
  final String kondisi_edc;
  final String status;
  final String detail_edc;
  final String note;
  final String foto_struk;
  final String foto_mesin;
  final String foto_toko;
  final String kondisi_merchant;
  final String request_merchant;
  final String tgl_pm;
  final String name;
  final String batch;
  final String idmerchant;
  final String midtid;
  final String tid;
  final String csi;
  final String sign;

  ModelPMResult({
    this.id,
    this.admintabelpm,
    this.namaitfs,
    this.serial,
    this.merchantid,
    this.assetid,
    this.kondisi_edc,
    this.status,
    this.detail_edc,
    this.kondisi_merchant,
    this.request_merchant,
    this.tgl_pm,
    this.name,
    this.batch,
    this.idmerchant,
    this.midtid,
    this.tid,
    this.csi,
    this.foto_mesin,
    this.foto_struk,
    this.foto_toko,
    this.note,
    this.sign,
  });

  factory ModelPMResult.fromJson(Map<String, dynamic> json) {
    return new ModelPMResult(
      id: json['id'],
      admintabelpm: json['id'],
      namaitfs: json['namaitfs'],
      serial: json['serial'],
      merchantid: json['merchantid'],
      assetid: json['assetid'],
      kondisi_edc: json['kondisi_edc'],
      status: json['status'],
      detail_edc: json['detail_edc'],
      kondisi_merchant: json['kondisi_merchant'],
      request_merchant: json['request_merchant'],
      tgl_pm: json['tgl_pm'],
      name: json['name'],
      batch: json['batch'],
      idmerchant: json['idmerchant'],
      midtid: json['midtid'],
      tid: json['tid'],
      csi: json['csi'],
      note: json['note'],
      foto_mesin: json['foto_mesin'],
      foto_toko: json['foto_toko'],
      foto_struk: json['foto_struk'],
      sign: json['sign'],





    );
  }
}

Please advice for, how to create listview menu in my Page Flutter. Thanks for your advice. and also how after the data is deleted in the search menu, data from the API returns to the list

Two solutions: you can copy paste run full code below
Solution 1: Search use current ListView page, In itemBuilder return data only fit your condition, such as string contains, if not return Container()

ListView.builder(
            itemCount: modelPM.results.length,
            itemBuilder: (context, i) {
              if (myController.text == "") return _listPM(i);
              if (myController.text != "" &&
                  modelPM.results[i].tid.contains(myController.text)) {
                return _listPM(i);
              } else {
                return Container();
              }
            },
          ),

demo 1

在此处输入图像描述

full code 1

import 'package:flutter/material.dart';
import 'dart:convert';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: PM(),
    );
  }
}

class PM extends StatefulWidget {
  @override
  _PMState createState() => _PMState();
}

class _PMState extends State<PM> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  void showInSnackBar(String value) {
    _scaffoldKey.currentState.showSnackBar(new SnackBar(
      content: new Text(value),
      backgroundColor: Colors.blueAccent,
    ));
  }

  final GlobalKey<RefreshIndicatorState> _refresh =
      GlobalKey<RefreshIndicatorState>();

  ModelPM modelPM;
  ModelPM _modelPM;

  bool loading = false;

  Future<Null> _fetchData() async {
    setState(() => loading = true);
    var value;

    /*SharedPreferences preferences = await SharedPreferences.getInstance();
    setState(() {
      value = preferences.getString("id");
    });

    final response = await http.post(BaseURL.systemTicket, body: {
      "key": BaseURL.apiKey,
      "method": "get",
      "resource": "tabel_pm",
      "filters[adminidtabelpm]": value,
    });*/

    /* if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      final pmModelFromJson = ModelPM.fromJson(data);

      setState(() {
        modelPM = pmModelFromJson;
        loading = false;
      });
    } else {
      showInSnackBar("Data Gagal Load");
    }*/
    String responsebody = '''
     { 
"status": 200,
"status_message" : "OK",
"result" : [
    {
    "id": "123",
    "name" : "name1",
    "notes" : "notes1",
    "midtid" : "midtid1",
    "tid" : "tid1",
    "csi" : "csi1",
    "status" : "abc"
    }
    ,
    {
    "id": "456",
    "name" : "name2",
    "notes" : "notes2",
    "midtid" : "midtid2",
    "tid" : "tid2",
    "csi" : "csi2",
     "status" : "def"
    }
]
}
    ''';
    final data = jsonDecode(responsebody);
    final pmModelFromJson = ModelPM.fromJson(data);
    setState(() {
      modelPM = pmModelFromJson;
      loading = false;
    });
  }

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

  _listPM(i) {
    final x = modelPM.results[i];
    return Card(
      elevation: 8.0,
      margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
      child: ListTile(
        onTap: () {
          /*Navigator.of(context).push(
              MaterialPageRoute(builder: (context) => DetilPM(x, _fetchData)));*/
        },
        contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
        title: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              x.name,
              textAlign: TextAlign.start,
              style: TextStyle(
                  fontSize: 12,
                  color: x.status == "Not Yet"
                      ? Colors.blue
                      : x.status == "Pending" ? Colors.red : Colors.green,
                  fontWeight: FontWeight.bold),
            ),
            Text(
              'Status : ' + x.status,
              textAlign: TextAlign.start,
              style: TextStyle(
                  fontSize: 12,
                  color: x.status == "Not Yet"
                      ? Colors.blue
                      : x.status == "Pending" ? Colors.red : Colors.green,
                  fontWeight: FontWeight.bold),
            ),
            SizedBox(
              height: 10,
            ),
          ],
        ),
        subtitle: Column(
          children: <Widget>[
            Row(
              children: <Widget>[
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text("MIDTID",
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text("TID",
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text("CSI",
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
              ],
            ),
            Row(
              children: <Widget>[
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text(x.midtid,
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text(x.tid,
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                      padding: EdgeInsets.only(left: 0.0),
                      child: Text(x.csi,
                          style: TextStyle(color: Colors.black, fontSize: 10))),
                ),
              ],
            )
          ],
        ),
        trailing:
            Icon(Icons.keyboard_arrow_right, color: Colors.black, size: 30.0),
      ),
    );
  }

  final myController = TextEditingController();

  @override
  void dispose() {
    // Clean up the controller when the widget is removed from the
    // widget tree.
    myController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextField(
          controller: myController,
          decoration:
              InputDecoration(border: InputBorder.none, hintText: 'Search'),
          onChanged: (value) {
            setState(() {});
          },
        ),
      ),
      key: _scaffoldKey,
      body: RefreshIndicator(
        onRefresh: _fetchData,
        key: _refresh,
        child: loading
            ? Center(child: CircularProgressIndicator())
            : ListView.builder(
                itemCount: modelPM.results.length,
                itemBuilder: (context, i) {
                  if (myController.text == "") return _listPM(i);
                  if (myController.text != "" &&
                      modelPM.results[i].tid.contains(myController.text)) {
                    return _listPM(i);
                  } else {
                    return Container();
                  }
                },
              ),
      ),
    );
  }
}

class ModelPM {
  final int status;
  final String status_message;
  final List<ModelPMResult> results;

  ModelPM({this.status, this.status_message, this.results});
  factory ModelPM.fromJson(Map<String, dynamic> json) {
    List<ModelPMResult> results = (json['result'] as List)
        .map((resultTicketJson) => ModelPMResult.fromJson(resultTicketJson))
        .toList();

    return ModelPM(
      status: json['status'],
      status_message: json['status_message'],
      results: results,
    );
  }
}

class ModelPMResult {
  final String id;
  final String admintabelpm;
  final String namaitfs;
  final String serial;
  final String merchantid;
  final String assetid;
  final String kondisi_edc;
  final String status;
  final String detail_edc;
  final String note;
  final String foto_struk;
  final String foto_mesin;
  final String foto_toko;
  final String kondisi_merchant;
  final String request_merchant;
  final String tgl_pm;
  final String name;
  final String batch;
  final String idmerchant;
  final String midtid;
  final String tid;
  final String csi;
  final String sign;

  ModelPMResult({
    this.id,
    this.admintabelpm,
    this.namaitfs,
    this.serial,
    this.merchantid,
    this.assetid,
    this.kondisi_edc,
    this.status,
    this.detail_edc,
    this.kondisi_merchant,
    this.request_merchant,
    this.tgl_pm,
    this.name,
    this.batch,
    this.idmerchant,
    this.midtid,
    this.tid,
    this.csi,
    this.foto_mesin,
    this.foto_struk,
    this.foto_toko,
    this.note,
    this.sign,
  });

  factory ModelPMResult.fromJson(Map<String, dynamic> json) {
    return new ModelPMResult(
      id: json['id'],
      admintabelpm: json['id'],
      namaitfs: json['namaitfs'],
      serial: json['serial'],
      merchantid: json['merchantid'],
      assetid: json['assetid'],
      kondisi_edc: json['kondisi_edc'],
      status: json['status'],
      detail_edc: json['detail_edc'],
      kondisi_merchant: json['kondisi_merchant'],
      request_merchant: json['request_merchant'],
      tgl_pm: json['tgl_pm'],
      name: json['name'],
      batch: json['batch'],
      idmerchant: json['idmerchant'],
      midtid: json['midtid'],
      tid: json['tid'],
      csi: json['csi'],
      note: json['note'],
      foto_mesin: json['foto_mesin'],
      foto_toko: json['foto_toko'],
      foto_struk: json['foto_struk'],
      sign: json['sign'],
    );
  }
}

Solution 2: Search with SearchDelegate , data actually display in another page
When click search button, open another page
demo

在此处输入图像描述

full demo code

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: SearchDemo(),
    );
  }
}


class SearchDemo extends StatefulWidget {
  static const String routeName = '/material/search';

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

class _SearchDemoState extends State<SearchDemo> {
  final _SearchDemoSearchDelegate _delegate = _SearchDemoSearchDelegate();
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  int _lastIntegerSelected;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        leading: IconButton(
          tooltip: 'Navigation menu',
          icon: AnimatedIcon(
            icon: AnimatedIcons.menu_arrow,
            color: Colors.white,
            progress: _delegate.transitionAnimation,
          ),
          onPressed: () {
            _scaffoldKey.currentState.openDrawer();
          },
        ),
        title: const Text('Numbers'),
        actions: <Widget>[
          IconButton(
            tooltip: 'Search',
            icon: const Icon(Icons.search),
            onPressed: () async {
              final int selected = await showSearch<int>(
                context: context,
                delegate: _delegate,
              );
              if (selected != null && selected != _lastIntegerSelected) {
                setState(() {
                  _lastIntegerSelected = selected;
                });
              }
            },
          ),
          //MaterialDemoDocumentationButton(SearchDemo.routeName),
          IconButton(
            tooltip: 'More (not implemented)',
            icon: Icon(
              Theme.of(context).platform == TargetPlatform.iOS
                  ? Icons.more_horiz
                  : Icons.more_vert,
            ),
            onPressed: () { },
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            MergeSemantics(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: const <Widget>[
                      Text('Press the '),
                      Tooltip(
                        message: 'search',
                        child: Icon(
                          Icons.search,
                          size: 18.0,
                        ),
                      ),
                      Text(' icon in the AppBar'),
                    ],
                  ),
                  const Text('and search for an integer between 0 and 100,000.'),
                ],
              ),
            ),
            const SizedBox(height: 64.0),
            Text('Last selected integer: ${_lastIntegerSelected ?? 'NONE' }.'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton.extended(
        tooltip: 'Back', // Tests depend on this label to exit the demo.
        onPressed: () {
          Navigator.of(context).pop();
        },
        label: const Text('Close demo'),
        icon: const Icon(Icons.close),
      ),
      drawer: Drawer(
        child: Column(
          children: <Widget>[
            const UserAccountsDrawerHeader(
              accountName: Text('Peter Widget'),
              accountEmail: Text('peter.widget@example.com'),
              currentAccountPicture: CircleAvatar(
                backgroundImage: AssetImage(
                  'people/square/peter.png',
                  package: 'flutter_gallery_assets',
                ),
              ),
              margin: EdgeInsets.zero,
            ),
            MediaQuery.removePadding(
              context: context,
              // DrawerHeader consumes top MediaQuery padding.
              removeTop: true,
              child: const ListTile(
                leading: Icon(Icons.payment),
                title: Text('Placeholder'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _SearchDemoSearchDelegate extends SearchDelegate<int> {
  final List<int> _data = List<int>.generate(100001, (int i) => i).reversed.toList();
  final List<int> _history = <int>[42607, 85604, 66374, 44, 174];

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      tooltip: 'Back',
      icon: AnimatedIcon(
        icon: AnimatedIcons.menu_arrow,
        progress: transitionAnimation,
      ),
      onPressed: () {
        close(context, null);
      },
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {

    final Iterable<int> suggestions = query.isEmpty
        ? _history
        : _data.where((int i) => '$i'.startsWith(query));

    return _SuggestionList(
      query: query,
      suggestions: suggestions.map<String>((int i) => '$i').toList(),
      onSelected: (String suggestion) {
        query = suggestion;
        showResults(context);
      },
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    final int searched = int.tryParse(query);
    if (searched == null || !_data.contains(searched)) {
      return Center(
        child: Text(
          '"$query"\n is not a valid integer between 0 and 100,000.\nTry again.',
          textAlign: TextAlign.center,
        ),
      );
    }

    return ListView(
      children: <Widget>[
        _ResultCard(
          title: 'This integer',
          integer: searched,
          searchDelegate: this,
        ),
        _ResultCard(
          title: 'Next integer',
          integer: searched + 1,
          searchDelegate: this,
        ),
        _ResultCard(
          title: 'Previous integer',
          integer: searched - 1,
          searchDelegate: this,
        ),
      ],
    );
  }

  @override
  List<Widget> buildActions(BuildContext context) {
    return <Widget>[
      if (query.isEmpty)
        IconButton(
          tooltip: 'Voice Search',
          icon: const Icon(Icons.mic),
          onPressed: () {
            query = 'TODO: implement voice input';
          },
        )
      else
        IconButton(
          tooltip: 'Clear',
          icon: const Icon(Icons.clear),
          onPressed: () {
            query = '';
            showSuggestions(context);
          },
        ),
    ];
  }
}

class _ResultCard extends StatelessWidget {
  const _ResultCard({this.integer, this.title, this.searchDelegate});

  final int integer;
  final String title;
  final SearchDelegate<int> searchDelegate;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return GestureDetector(
      onTap: () {
        searchDelegate.close(context, integer);
      },
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: <Widget>[
              Text(title),
              Text(
                '$integer',
                style: theme.textTheme.headline.copyWith(fontSize: 72.0),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _SuggestionList extends StatelessWidget {
  const _SuggestionList({this.suggestions, this.query, this.onSelected});

  final List<String> suggestions;
  final String query;
  final ValueChanged<String> onSelected;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return ListView.builder(
      itemCount: suggestions.length,
      itemBuilder: (BuildContext context, int i) {
        final String suggestion = suggestions[i];
        return ListTile(
          leading: query.isEmpty ? const Icon(Icons.history) : const Icon(null),
          title: RichText(
            text: TextSpan(
              text: suggestion.substring(0, query.length),
              style: theme.textTheme.subhead.copyWith(fontWeight: FontWeight.bold),
              children: <TextSpan>[
                TextSpan(
                  text: suggestion.substring(query.length),
                  style: theme.textTheme.subhead,
                ),
              ],
            ),
          ),
          onTap: () {
            onSelected(suggestion);
          },
        );
      },
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM