WebView自定义滚动视图+浮动AppBar

13

我想创建一个屏幕,其中包含一个WebView(来自webview_flutter: ^0.3.5+3),以及一个我希望在用户滚动时可以滚动到屏幕外的AppBar

我偶然发现了这个指南,并尝试实现类似的东西,但是没有成功。
是否有一种方法可以在CustomScrollView中使用SliversWebView,或者目前还不支持?

如果我在我的SliverChildListDelegate中创建常规小部件(例如我尝试过RowTextContainer等),可以使滚动应用栏正常工作,但是对于WebView,我就没有那么幸运了。

@override
Widget build(BuildContext context) {
  return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            title: const Text("Heading"),
            floating: true,
          ),
          SliverList(
            delegate: SliverChildListDelegate([
              Container(
                child: WebView(
                  initialUrl: url,
                  javascriptMode: JavascriptMode.unrestricted,
                ),
              )
            ]
            ),
          )
        ],
      )
  );
}

欢迎任何指针/建议/阅读文档。

编辑悬赏

jordan-davies提供的解决方案可以工作,但很不流畅。 每当SliverAppBar滚动时,WebView尝试重新调整大小以填充剩余的视口。这会导致非常不流畅/缓慢的体验。

@override
Widget build(BuildContext context) {
  return CustomScrollView(
    slivers: <Widget>[
      SliverAppBar(
        title: const Text("Heading"),
        floating: true,
      ),
      SliverFillRemaining(
        child: WebView(initialUrl: "http://stackoverflow.com"),
      )
    ],
  );
}

上面的代码的GIF图
有更好的方法吗?

3个回答

1
我原本想发表评论,但内容太长了无法适应。我可以分享一下为什么使用当前插件状态不可能实现这一点的看法。默认情况下,Webview 仅在没有其他视图声明该手势时才响应拖动手势。另一方面,滚动片段(例如 SliverList)需要用于使 SliverAppBar 向上滚动, 默认情况下会消耗所有拖动滚动手势,尽管您可以通过提供 noScrollPhysics 来禁用它,但是一旦 WebView 覆盖整个屏幕,就无法向滚动片段报告以重新开始消耗滚动。因此,解决方案是修改 WebView 插件 本身以提供拖动手势的回调,希望 Flutter 团队能尽快实现此功能。

我在 Github 上开了一个官方的 bug 报告;https://github.com/flutter/flutter/issues/31243 - timr
如果您点赞,他们首先解决问题的可能性更高。 - timr
@Tim,已完成,请检查我的答案,其中有部分解决方案。 - Saed Nabil

0
经过多次尝试和错误,我发现可以通过以下方式使用gestureRecognizers来解决类似问题:
  @override
  Widget build(BuildContext context) {
    return SliverFillRemaining(
      child: WebView(
        initialUrl: url,
        javascriptMode: JavascriptMode.unrestricted,
        gestureRecognizers: {
          Factory<VerticalDragGestureRecognizer>(
            () => VerticalDragGestureRecognizer(),
          ),
        },
      ),
    );
  }

0

我认为你应该考虑使用SliverFillRemaining或者SliverFillViewport代替SliverList。这里有一个使用SliverFillRemaining的例子:

https://docs.flutter.io/flutter/widgets/SliverFillRemaining-class.html

@override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
          title: const Text("Heading"),
          floating: true,
        ),
        SliverFillRemaining(
          child: WebView(initialUrl: "http://stackoverflow.com"),
        )
      ],
    );
  }

2
谢谢。这将呈现WebView,但CustomScrollView似乎在AppBar滚动屏幕后消耗了所有的滚动事件。我相信有一种方法可以在那一点上将滚动事件委托给WebView,但我的Flutter技能还不够高。现在要尝试SliverFillViewport。 - user3403083
SilverFillViewport也没有成功。WebView可以渲染,但是当你滚动WebView时,WebView会被复制到原始WebView边界结束的点之后。根据文档,我认为SliverChildBuilderDelegate在超出初始视口后回调以惰性地创建更多子项。屏幕上看到的情况似乎表明正在发生这种情况。所以我又回到了原点。 - user3403083
嗯,也许使用 WebView 不太可能实现。我一直在尝试使用 NestedScrollView 替代 CustomScrollView,但是无法使其正常工作。如果您想尝试,这里有一个很好的例子:https://docs.flutter.io/flutter/widgets/NestedScrollView-class.html。 - Jordan Davies
你找到解决方法了吗? - timr
我尝试了提供的解决方案,但似乎当应用栏滚动出视图时,Webview 会尝试调整大小。这使得体验非常卡顿/缓慢。 我已经在问题上设置了赏金。 - timr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接