2

我正在尝试构建一个可搜索的下拉列表,该下拉列表将在每次单击按钮时从服务中加载值。因此,为此我将 DropDownButton 和 TextField 封装在 Stack Widget 中。

在按键上,我们得到了 api 的响应,到目前为止一切都很好。但是从 api 下拉列表中获取数据后没有打开。经过一番挖掘,我才知道它没有打开,因为我们需要手动点击它才能打开,但由于它在堆栈中,第二个孩子是 TextField,我无法点击它。

但是以编程方式打开 DropDownButton 按钮是不可能的。所以我尝试了https://stackoverflow.com/a/59499191/10423593的第二个解决方案,但它没有用。

下面是我的代码,没有来自stackoverflow的解决方案。

import 'package:flutter/material.dart';
import 'package:giphy/services/gifs_service.dart';
import 'package:giphy/shared/autocomplete.dart';

class TestDropDown extends StatefulWidget {
  // const TestDropDown({Key? key}) : super(key: key);
  @override
  _TestDropDownState createState() => _TestDropDownState();
}

class _TestDropDownState extends State<TestDropDown> {
  final GifyService _service = GifyService();

  final TextEditingController _gifSearchController = TextEditingController();

  List<SearchData> _dropDownResult = <SearchData>[];

  GlobalKey key = GlobalKey();

  // T? _findChildWidgetFromKey<T extends Widget>(
  //     BuildContext? context, T childWidget) {
  //   T? detector;
  //   context!.visitChildElements((element) {
  //     if (element.widget == childWidget) {
  //       detector = element.widget as T;
  //     }
  //   });

  //   return detector;
  // }

  Widget _buildDropDown(List<SearchData> searchData) => DropdownButton<String>(
        isExpanded: true,
        key: key,
        onChanged: (String? value) {},
        items: searchData
            .map(
              (e) => DropdownMenuItem<String>(
                child: Text(e.name ?? ''),
                value: e.name ?? '',
              ),
            )
            .toList(),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          _buildDropDown(_dropDownResult),
          Container(child: () {
            if (_dropDownResult.length > 0) {
              _buildDropDown(_dropDownResult);
            }
          }()),
          TextField(
            controller: _gifSearchController,
            decoration: InputDecoration(
              border: OutlineInputBorder(
                borderSide: BorderSide(width: 0.5),
                borderRadius: BorderRadius.circular(21),
              ),
            ),
            onChanged: (String value) async {
              AutoComplete result = await _service.getSearchKeywords(value);
              setState(() {
                _dropDownResult = result.data;
              });
            },
          ),
        ],
      ),
    );
  }
}
4

3 回答 3

1

如果您正在寻找自动完成文本字段,那么您可以使用 autocomplete_textfield包。

或者,如果您想自己构建它,那么您可以通过使用容器而不是下拉菜单来尝试不同的方法。

于 2021-09-27T04:34:03.650 回答
0

尝试使用:https ://pub.dev/packages/dropdown_search 第 1 步:您请求所有数据 第 2 步:使用库您可以搜索项目

于 2021-09-27T04:36:08.513 回答
0

在尝试了一些软件包之后。我无法基于 api 调用进行颤振自动完成。

所以决定尝试其他方法并 在颤振中使用Overlay

import 'dart:async';

import 'package:flutter/material.dart';

class TestDropDown extends StatefulWidget {
  @override
  _TestDropDownState createState() => _TestDropDownState();
}

class _TestDropDownState extends State<TestDropDown> {
  late OverlayEntry _overlayEntry;
  Timer? _debounce;
  _showOverlay(BuildContext context) {
    OverlayState? state = Overlay.of(context);
    final RenderBox? box = key.currentContext!.findRenderObject() as RenderBox;
    Size size = box!.size;
    Offset position = box.localToGlobal(Offset.zero);
    _overlayEntry = OverlayEntry(
      builder: (context) => Positioned(
        top: size.height + position.dy,
        left: position.dx,
        child: Card(
          child: Container(
              height: 200,
              width: size.width,
              decoration: BoxDecoration(
                border: Border.all(),
              ),
              child: Column(
                children: [
                  Container(
                    width: size.width,
                    child: IconButton(
                      onPressed: () {
                        if (_overlayEntry.mounted) {
                          _overlayEntry.remove();
                        }
                      },
                      icon: Icon(Icons.close),
                      alignment: Alignment.topRight,
                    ),
                  ),
                  Expanded(
                    child: ListView(
                      children: []..addAll(List.generate(
                          200, (index) => Text(index.toString()))),
                    ),
                  ),
                ],
              )),
        ),
      ),
    );
    state!.insert(_overlayEntry);
  }

  final key = GlobalKey();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(50),
        child: Column(
          children: [
            TextField(
              key: key,
              onChanged: (String searchText) {
                if (_debounce?.isActive ?? false) _debounce!.cancel();
                _debounce = Timer(const Duration(milliseconds: 500), () {
                  print(searchText);
                });
              },
            ),
            ElevatedButton(
              onPressed: () {
                _showOverlay(context);
              },
              child: Text('Press Me'),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_overlayEntry.mounted) {
            _overlayEntry.remove();
          }
        },
      ),
    );
  }
}

在此处输入图像描述

于 2021-10-02T13:16:43.470 回答