如何使SliverPersistentHeader达到“过度增长"状态.

编程入门 行业动态 更新时间:2024-10-09 23:20:45
本文介绍了如何使SliverPersistentHeader达到“过度增长"状态.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我在我的CustomScrollView中使用SliverPersistentHeader来拥有一个持久的标头,该标头在用户滚动时会缩小和增长,但是当达到最大尺寸时,它会变得有点僵硬,因为它不会过度增长"

I'm using a SliverPersistentHeader in my CustomScrollView to have a persistent header that shrinks and grows when the user scrolls, but when it reaches its maximum size it feels a bit stiff since it doesn't "overgrow".

以下是我想要的行为(来自Spotify应用)的视频以及我的行为:

Here is a video of the behaviour I want (from the Spotify app) and the behaviour I have:

.

推荐答案

在寻找此问题的解决方案时,我遇到了三种不同的解决方法:

While looking for a solution for this problem, I came across three different ways to solve it:

  • 创建一个包含CustomScrollView和标题小部件(覆盖在滚动视图顶部)的Stack,为CustomScrollView提供一个ScrollController并将控制器传递给标题小部件以调整其大小
  • 使用ScrollController,将其传递到CustomScrollView,然后使用控制器的值来调整SliverPersistentHeader的maxExtent(这是推荐Eugene ).
  • 写我自己的Sliver来做我想要的事情.
  • Create a Stack that contains the CustomScrollView and a header widget (overlaid on top of the scroll view), provide a ScrollController to the CustomScrollView and pass the controller to the header widget to adjust its size
  • Use a ScrollController, pass it to the CustomScrollView and use the value of the controller to adjust the maxExtent of the SliverPersistentHeader (this is what Eugene recommended).
  • Write my own Sliver to do exactly what I want.
  • 我在解决方案1和解决方案上遇到了问题2:

    I ran into problems with solution 1 & 2:

  • 此解决方案对我来说似乎有点骇人听闻".我还遇到了一个问题,即拖动"标题不再滚动,因为标题不再位于里面 了.
  • 在滚动过程中调整条子的大小会产生奇怪的副作用.值得注意的是,在滚动过程中,页眉和下方条子之间的距离会增加.
  • 这就是为什么我选择解决方案3的原因.我确定实现它的方式并不是最好的,但是它完全可以按照我的意愿进行工作:

    That's why I opted for solution 3. I'm sure the way I implemented it, is not the best, but it works exactly as I want:

    import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'dart:math' as math; /// The delegate that is provided to [ElSliverPersistentHeader]. abstract class ElSliverPersistentHeaderDelegate { double get maxExtent; double get minExtent; /// This acts exactly like `SliverPersistentHeaderDelegate.build()` but with /// the difference that `shrinkOffset` might be negative, in which case, /// this widget exceeds `maxExtent`. Widget build(BuildContext context, double shrinkOffset); } /// Pretty much the same as `SliverPersistentHeader` but when the user /// continues to drag down, the header grows in size, exceeding `maxExtent`. class ElSliverPersistentHeader extends SingleChildRenderObjectWidget { final ElSliverPersistentHeaderDelegate delegate; ElSliverPersistentHeader({ Key key, ElSliverPersistentHeaderDelegate delegate, }) : this.delegate = delegate, super( key: key, child: _ElSliverPersistentHeaderDelegateWrapper(delegate: delegate)); @override _ElPersistentHeaderRenderSliver createRenderObject(BuildContext context) { return _ElPersistentHeaderRenderSliver( delegate.maxExtent, delegate.minExtent); } } class _ElSliverPersistentHeaderDelegateWrapper extends StatelessWidget { final ElSliverPersistentHeaderDelegate delegate; _ElSliverPersistentHeaderDelegateWrapper({Key key, this.delegate}) : super(key: key); @override Widget build(BuildContext context) => LayoutBuilder(builder: (context, constraints) { final height = constraints.maxHeight; return delegate.build(context, delegate.maxExtent - height); }); } class _ElPersistentHeaderRenderSliver extends RenderSliver with RenderObjectWithChildMixin<RenderBox> { final double maxExtent; final double minExtent; _ElPersistentHeaderRenderSliver(this.maxExtent, this.minExtent); @override bool hitTestChildren(HitTestResult result, {@required double mainAxisPosition, @required double crossAxisPosition}) { if (child != null) { return child.hitTest(result, position: Offset(crossAxisPosition, mainAxisPosition)); } return false; } @override void performLayout() { /// The amount of scroll that extends the theoretical limit. /// I.e.: when the user drags down the list, although it already hit the /// top. /// /// This seems to be a bit of a hack, but I haven't found a way to get this /// information in another way. final overScroll = constraints.viewportMainAxisExtent - constraints.remainingPaintExtent; /// The actual Size of the widget is the [maxExtent] minus the amount the /// user scrolled, but capped at the [minExtent] (we don't want the widget /// to become smaller than that). /// Additionally, we add the [overScroll] here, since if there *is* /// "over scroll", we want the widget to grow in size and exceed /// [maxExtent]. final actualSize = math.max(maxExtent - constraints.scrollOffset + overScroll, minExtent); /// Now layout the child with the [actualSize] as `maxExtent`. child.layout(constraints.asBoxConstraints(maxExtent: actualSize)); /// We "clip" the `paintExtent` to the `maxExtent`, otherwise the list /// below stops moving when reaching the border. /// /// Tbh, I'm not entirely sure why that is. final paintExtent = math.min(actualSize, maxExtent); /// For the layout to work properly (i.e.: the following slivers to /// scroll behind this sliver), the `layoutExtent` must not be capped /// at [minExtent], otherwise the next sliver will "stop" scrolling when /// [minExtent] is reached, final layoutExtent = math.max(maxExtent - constraints.scrollOffset, 0.0); geometry = SliverGeometry( scrollExtent: maxExtent, paintExtent: paintExtent, layoutExtent: layoutExtent, maxPaintExtent: maxExtent, ); } @override void paint(PaintingContext context, Offset offset) { if (child != null) { /// This sliver is always displayed at the top. context.paintChild(child, Offset(0.0, 0.0)); } } }

    更多推荐

    如何使SliverPersistentHeader达到“过度增长"状态.

    本文发布于:2023-10-16 14:13:13,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1497803.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:状态   SliverPersistentHeader   quot

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!