使用箭头键逐个选择 ListView 的每个项目

Select each item of ListView one by one with arrow keys

提问人:arkarwine 提问时间:11/17/2023 更新时间:11/17/2023 访问量:28

问:

基本上,我想要实现的是一个像 YouTube 那样的搜索栏,您可以在其中使用箭头键逐个选择搜索结果。

我试着玩,但我无法想象它。FocusNode

颤振 飞镖

评论

0赞 Md. Kamrul Amin 11/17/2023
这是针对 Flutter Web 的吗?
0赞 arkarwine 11/17/2023
不是专门针对网络的。我正在尝试构建一个包括网络在内的跨平台应用程序。

答:

0赞 Mehroze Zaidi 11/30/2023 #1

请试一试这段代码,它是来自 Flutter 框架本身的高度可定制的搜索栏。它还包括将焦点从一个元素转移到其他元素。注意:我只在网上检查过。

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Search Bar with Suggestions'),
        ),
        body: Center(
          child: SearchBar(),
        ),
      ),
    );
  }
}

class SearchBar extends StatefulWidget {
  const SearchBar({super.key});

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

class _SearchBarState extends State<SearchBar> {
  TextEditingController _searchController = TextEditingController();
  FocusNode _focusNode = FocusNode();
  int _selectedIndex = -1;

  @override
  void initState() {
    super.initState();
    _focusNode.addListener(() {
      if (_focusNode.hasFocus) {
        setState(() {
          _selectedIndex = -1;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Autocomplete<String>(
        optionsBuilder: (TextEditingValue textEditingValue) {
          return _suggestions
              .where((String suggestion) =>
              suggestion.toLowerCase().contains(textEditingValue.text.toLowerCase()))
              .toList();
        },
        onSelected: (String selectedValue) {
          print('Selected: $selectedValue');
        },
        fieldViewBuilder: (BuildContext context,
            TextEditingController controller,
            FocusNode focusNode,
            VoidCallback onFieldSubmitted) {
          _focusNode = focusNode;
          _searchController = controller;
          return TextField(
            controller: controller,
            focusNode: focusNode,
            onChanged: (String value) {
              // Add any additional logic when text changes
            },
            onSubmitted: (String value) {
              // Add any logic when the user submits the search
              onFieldSubmitted();
            },
            decoration: InputDecoration(
              prefixIcon: Icon(Icons.search),
              hintText: 'Search',
            ),
          );
        },
        optionsViewBuilder: (context, onSelected, options) {

          return Align(
            alignment: Alignment.topLeft,
            child: Material(
              elevation: 4.0,
              child: ConstrainedBox(
                constraints: BoxConstraints(maxHeight: 200),
                child: ListView.builder(
                  padding: EdgeInsets.zero,
                  shrinkWrap: true,
                  itemCount: options.length,
                  itemBuilder: (BuildContext context, int index) {
                    final String option = options.elementAt(index);
                    return InkWell(
                      onTap: () {
                        onSelected(option);
                      },
                      child: Builder(
                          builder: (BuildContext context) {
                            final bool highlight = AutocompleteHighlightedOption.of(context) == index;
                            if (highlight) {
                              SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
                                Scrollable.ensureVisible(context, alignment: 0.5);
                              });
                            }
                            return Container(
                              color: highlight ? Theme.of(context).focusColor : null,
                              padding: const EdgeInsets.all(16.0),
                              child: Text(option),
                            );
                          }
                      ),
                    );
                  },
                ),
              ),
            ),
          );
        },
    
      ),
    );
  }

  final List<String> _suggestions = [
    'Flutter',
    'Dart',
    'Widgets',
    'YouTube',
    'Search',
    'Example',
  ];
}