Dart 如何在“颤振”下拉按钮中搜索

Dart 如何在“颤振”下拉按钮中搜索,dart,flutter,filtering,dropdown,Dart,Flutter,Filtering,Dropdown,我有一个本地json格式的国家名称列表。我可以加载我的本地json并分配给下拉按钮。json文件中有193个国家,如下图所示。如果我想选择美国,用户必须一直向下滚动。如何输入国家名称,例如;如果我的用户输入U或U,下拉列表可以快速过滤并列出所有以U开头的国家,如美国如何搜索颤振下拉按钮项目 { "country": [ { "countryCode": "AD", "countryName": "An

我有一个本地json格式的国家名称列表。我可以加载我的本地json并分配给下拉按钮。json文件中有193个国家,如下图所示。如果我想选择美国,用户必须一直向下滚动。如何输入国家名称,例如;如果我的用户输入U或U,下拉列表可以快速过滤并列出所有以U开头的国家,如美国如何搜索颤振下拉按钮项目

{
    "country": [
            {
                "countryCode": "AD",
                "countryName": "Andorra",
                "currencyCode": "EUR",
                "isoNumeric": "020"
            },
            {
                "countryCode": "AE",
                "countryName": "United Arab Emirates",
                "currencyCode": "AED",
                "isoNumeric": "784"
            },
            {
                "countryCode": "AF",
                "countryName": "Afghanistan",
                "currencyCode": "AFN",
                "isoNumeric": "004"
            },

一种方法是使用
TextEditingController
过滤
ListView
,如下所示:

class YourPage extends StatefulWidget {
  @override
  State createState() => YourPageState();
}

class YourPageState extends State<YourPage> {
  List<Country> countries = new List<Country>();
  TextEditingController controller = new TextEditingController();
  String filter;

  @override
  void initState() {
    super.initState();
    //fill countries with objects
    controller.addListener(() {
      setState(() {
        filter = controller.text;
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Material(
        color: Colors.transparent,
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            new Padding(
                padding: new EdgeInsets.only(top: 8.0, left: 16.0, right: 16.0),
                child: new TextField(
                  style: new TextStyle(fontSize: 18.0, color: Colors.black),
                  decoration: InputDecoration(
                    prefixIcon: new Icon(Icons.search),
                    suffixIcon: new IconButton(
                      icon: new Icon(Icons.close),
                      onPressed: () {
                        controller.clear();
                        FocusScope.of(context).requestFocus(new FocusNode());
                      },
                    ),
                    hintText: "Search...",
                  ),
                  controller: controller,
                )),
            new Expanded(
              child: new Padding(
                  padding: new EdgeInsets.only(top: 8.0),
                  child: _buildListView()),
            )
          ],
        ));
  }

  Widget _buildListView() {
    return ListView.builder(
        itemCount: countries.length,
        itemBuilder: (BuildContext context, int index) {
          if (filter == null || filter == "") {
            return _buildRow(countries[index]);
          } else {
            if (countries[index].countryName
                .toLowerCase()
                .contains(filter.toLowerCase())) {
              return _buildRow(countries[index]);
            } else {
              return new Container();
            }
          }
        });
  }

  Widget _buildRow(Country c) {
    return new ListTile(
        title: new Text(
          c.countryName,
        ),
        subtitle: new Text(
          c.countryCode,
        ));
  }
}
class YourPage扩展StatefulWidget{
@凌驾
State createState()=>YourPageState();
}
类YourPageState扩展状态{
列表国家=新列表();
TextEditingController=新的TextEditingController();
串滤波器;
@凌驾
void initState(){
super.initState();
//用对象填充国家
controller.addListener(){
设置状态(){
filter=controller.text;
});
});
}
@凌驾
无效处置(){
super.dispose();
controller.dispose();
}
@凌驾
小部件构建(构建上下文){
退回新材料(
颜色:颜色。透明,
子:新列(
crossAxisAlignment:crossAxisAlignment.stretch,
儿童:[
新填料(
填充:仅限新边集(顶部:8.0,左侧:16.0,右侧:16.0),
孩子:新文本字段(
样式:新的文本样式(字体大小:18.0,颜色:Colors.black),
装饰:输入装饰(
前缀:新图标(Icons.search),
suffixIcon:新图标按钮(
图标:新图标(图标。关闭),
已按下:(){
controller.clear();
FocusScope.of(context).requestFocus(newfocusnode());
},
),
hintText:“搜索…”,
),
控制器:控制器,
)),
新扩展(
孩子:新的填充物(
填充:仅限新边缘组(顶部:8.0),
子项:_buildListView()),
)
],
));
}
小部件_buildListView(){
返回ListView.builder(
itemCount:countries.length,
itemBuilder:(构建上下文,int索引){
if(filter==null | | filter==“”){
返回(国家[指数]);
}否则{
if(国家[索引]).countryName
.toLowerCase()
.contains(filter.toLowerCase()){
返回(国家[指数]);
}否则{
返回新容器();
}
}
});
}
Widget\u buildRow(国家c){
返回新的ListTile(
标题:新文本(
c、 国名,
),
字幕:新文本(
c、 国家代码,
));
}
}

您可以使用可搜索的下拉包:

下面是我的示例代码

如果您使用像我的示例那样的类列表,请确保您放置了以下内容

  @override
  String toString() {
    return this.key;
  }
我找到了另一个插件。 它有很多特性(例如
InputDecoration
),看起来像
TextFormField()
。因此,您的UI将是相同的

我建议您使用这个惊人的插件:


你误解了我的问题。我的下拉按钮在列表视图中,我将数据分配给我的下拉按钮。我正在寻找方法,以便通过用户交互搜索或过滤下拉按钮。@Nick SnakeyHips是对的。您必须在对话框中使用带有TextField列小部件的ListView,而不是下拉列表。事实上,对于像country list这样的大型列表,下拉列表是一个糟糕的选择。我的意思是它不是html。这是一个很好的解决方案,但是颤振不会一次加载所有的国家,所以我们不能过滤中低级别的记录。一个更好的解决方案是使用另一个过滤过的国家列表,并根据过滤器填充/清除该列表,我们可以将此代码直接放入侦听器中。