获取 CustomScrollView 中小部件的位置

问题描述 投票:0回答:1

当小部件位于 CustomScrollView > SliverToBoxAdapter 中时如何获取小部件位置。我的小部件 ZoomItem 通过创建带有覆盖层的新小部件进行缩放,但是当我向上或向下滚动,或者当我更改窗口大小时,覆盖层会出现在一边。为什么“最终 Offset offset = renderBox.localToGlobal(Offset.zero);”仍然返回相同的位置?有没有办法更新渲染框?为什么我的代码中没有更新偏移量?

缩放项目:

class ZoomItem extends ConsumerStatefulWidget {
  final Widget child;

  const ZoomItem({Key? key, required this.child}) : super(key: key);

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

class _ZoomItemState extends ConsumerState<ZoomItem>
    with SingleTickerProviderStateMixin {
  OverlayEntry? overlayEntry;

  late bool hasReachedTop;
  late double height, width, xPosition, yPosition;

  late AnimationController _animationController;
  late Animation<double> animTween;

  @override
  void initState() {
    super.initState();
    hasReachedTop = true;
    _animationController = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 400));

    _animationController.addListener(() {
      if (_animationController.isDismissed) {
        closeDropDown();
      }
    });
    animTween = Tween<double>(begin: 1.0, end: 2.0).animate(
        CurvedAnimation(parent: _animationController, curve: Curves.easeInOut));


    final scrollController = ref.read(scrollControllerProvider);
    scrollController.addListener(() {
      if (scrollController.position.atEdge) {
        if (scrollController.position.pixels == 0) {
          hasReachedTop = true;
        } else {
          hasReachedTop = false;
        }
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
        onEnter: (onEnter) {
          insertOverlay(context);
        },
        onExit: (onExit) {
          if (!_animationController.isAnimating) {
            closeDropDown();
          }
        },
        child: widget.child);
  }

  void insertOverlay(BuildContext context) {
    closeDropDown();
    findDropdownData(context);
    overlayEntry = _createOverlay();
    Overlay.of(context)!.insert(overlayEntry!);
  }

  OverlayEntry _createOverlay() {
    return OverlayEntry(builder: (context) {
      return Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
              top: yPosition,
              left: xPosition,
              height: height,
              width: width,
              child: MouseRegion(
                  onEnter: (onEnter) {
                    _animationController.forward();
                  },
                  onExit: (onExit) {
                    _animationController.reverse();
                  },
                  child:
                      ScaleTransition(scale: animTween, child: widget.child))),
        ],
      );
    });
  }

  void findDropdownData(BuildContext context) {
    final RenderBox renderBox = context.findRenderObject()! as RenderBox;


    height = renderBox.size.height;
    width = renderBox.size.width;
    final Offset offset = renderBox.localToGlobal(Offset.zero);
    xPosition = offset.dx - kPaddingHorizontal;
    final top = hasReachedTop ? kSliverTop : 0;
    yPosition = offset.dy - top;
  }

  void closeDropDown() {
    if (overlayEntry != null) {
      overlayEntry!.remove();
      overlayEntry = null;
    }
  }
}

GridView交错:

class GridViewStaggered extends StatelessWidget {
  final ResponsiveLayoutSize currentSize;
  final List<Item> listItem;
  const GridViewStaggered({Key? key, required this.currentSize, required this.listItem}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StaggeredGrid.count(

        children: [

          for(int i = 0 ; i < listItem.length; i++)
            StaggeredGridTile.count(
              crossAxisCellCount: i % 2 == 0 ? 2:1,
              mainAxisCellCount: i % 2 == 0 ? 2:1,
              child: i.isEven? ItemCard(
                item: listItem[i],
              ):ZoomItem(
                child: ItemCard(
                  item: listItem[i],
                ),
              ),
            )
        ],
        crossAxisCount: 4);
  }
}
flutter flutter-layout flutter-web flutter-animation
1个回答
0
投票

尝试这样,https://diamantidis.github.io/2021/10/10/exploring-flutter-scrollable-ensurevisible,这是一个稍微不同的解决方案

© www.soinside.com 2019 - 2024. All rights reserved.