dart 为什么在Flutter Web中使用Overlay时ListTile的onTap回调不起作用?

oalqel3c  于 2023-06-03  发布在  Flutter
关注(0)|答案(1)|浏览(139)

**框架: Flutter **
平台:Web

我有以下代码呈现一个TextField。当TextField具有焦点时,ListView使用Overlay呈现在TextField下方。这个小部件的目的是作为一个下拉菜单。但是,在点击ListView内部的ListTile的onTap()回调函数时什么也不做!

import 'package:flutter/material.dart';

class CountriesField extends StatefulWidget {
  @override
  _CountriesFieldState createState() => _CountriesFieldState();
}

class _CountriesFieldState extends State<CountriesField> {
  final FocusNode _focusNode = FocusNode();

  OverlayEntry? _overlayEntry;

  List<String> countries = ['Lebanon', 'Syria', 'India'];

  @override
  void initState() {
    super.initState();
    _focusNode.addListener(() {
      if (_focusNode.hasFocus) {
        _overlayEntry = _createOverlayEntry();
        Overlay.of(context).insert(_overlayEntry!);
      } else {
        _overlayEntry!.remove();
      }
    });
  }

  OverlayEntry _createOverlayEntry() {
    RenderBox? renderBox = context.findRenderObject() as RenderBox?;
    var size = renderBox?.size;
    var offset = renderBox?.localToGlobal(Offset(0, size!.height + 5.0));

    return OverlayEntry(
      builder: (context) => Positioned(
        left: offset?.dx,
        top: offset?.dy,
        width: size?.width,
        child: Material(
          elevation: 4.0,
          child: SizedBox(
            width: 200,
            height: 300,
            child: ListView.builder(
              padding: EdgeInsets.zero,
              itemCount: countries.length,
              itemBuilder: (BuildContext context, index) {
                return ListTile(
                  title: Text(countries[index]),
                  onTap: () {
                    print(countries[index]);
                  },
                );
              },
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _focusNode.dispose();
    _overlayEntry?.remove();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      focusNode: _focusNode,
      decoration: InputDecoration(labelText: 'Country'),
    );
  }
}

**P.S.:**我知道许多下拉和搜索下拉包已经可用,但是,我需要做一个相当具体的下拉搜索小部件的一个项目,我正在做,需要解决这个问题.

dm7nw8vv

dm7nw8vv1#

要“绘制”下拉列表,需要CompositedTransformTargetCompositedTransformFollower
您还需要layerLink将它们链接在一起,
这是添加它们之后的结果:

import 'package:flutter/material.dart';

class CountriesField extends StatefulWidget {
  @override
  _CountriesFieldState createState() => _CountriesFieldState();
}

class _CountriesFieldState extends State<CountriesField> {
  final FocusNode _focusNode = FocusNode();

  OverlayEntry? _overlayEntry;
  final GlobalKey _widgetKey = GlobalKey();
  final layerLink = LayerLink();
  List<String> countries = ['Lebanon', 'Syria', 'India'];

  @override
  void initState() {
    super.initState();
    _focusNode.addListener(() {
      if (_focusNode.hasFocus) {
        _overlayEntry = _createOverlayEntry();
        Overlay.of(context).insert(_overlayEntry!);
      } else {
        _overlayEntry!.remove();
      }
    });
  }

  OverlayEntry _createOverlayEntry() {
    RenderBox? renderBox = context.findRenderObject() as RenderBox?;
    var size = renderBox?.size;
    var offset = renderBox?.localToGlobal(Offset(0, size!.height + 5.0));

    return OverlayEntry(
      builder: (context) => CompositedTransformFollower(
        link: layerLink,
        showWhenUnlinked: false,
        followerAnchor:  Alignment.bottomCenter,
        targetAnchor: Alignment.bottomCenter,
        offset: offset ?? Offset(0, 0),
        child: Material(
          elevation: 4.0,
          child: Container(
            width: 200,
            height: 300,
            alignment: Alignment.center,
            child:  ListView.builder(
              padding: EdgeInsets.zero,
              itemCount: countries.length,
              itemBuilder: (BuildContext context, index) {
                return ListTile(
                  title: Text(countries[index]),
                  onTap: () {
                    print(countries[index]);
                  },
                );
              },
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _focusNode.dispose();
    _overlayEntry?.remove();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: CompositedTransformTarget(
          link: layerLink,
          child: TextFormField(
            key: _widgetKey,
            focusNode: _focusNode,
            decoration: InputDecoration(labelText: 'Country'),
          ),
        ));
  }
}

相关问题