WebView CustomScrollView + Floating AppBar
Asked Answered
M

3

15

I am trying to create a screen that has a WebView (from webview_flutter: ^0.3.5+3) and an AppBar that I want to scroll offscreen on user scroll.

I stumbled upon this guide and tried implementing something similar, but no dice.
Is there a way to use a WebView in a CustomScrollView with Slivers or is this not supported yet?

I can get the scrolling app bar to work if I create regular Widgets in my SliverChildListDelegate (I tried Row, Text, Container etc.), but had no luck with a 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,
                ),
              )
            ]
            ),
          )
        ],
      )
  );
}

Any pointers/suggestions/RTFMs welcome.

EDIT BOUNTY

The solution provided by jordan-davies works but is very choppy. Whenever the SliverAppBar is scrolled away the WebView tries to resize itself to fill the remaining viewport. This makes for a very choppy/slow experience.

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

gif of code above
Is there a better way?

Merth answered 16/1, 2019 at 15:8 Comment(0)
P
1

I actually wanted to make a comment but it is too long to fit

I can give you my view for why it is not possible to do that with the current state of the plugin ,by default the Webview only respond to drag gesture when no other views claim that gesture. On the other hand, Scrolling slivers like SliverList, which is needed to make the SliverAppBar to scroll up ,by default consumes all drag scrolling gestures -although you can disable that by providing noScrollPhysics - but once the WebView cover all the screen there is actually noway to report back to the slivers to start consume scroll again .

So the solution is to modify the WebView plugin itself to provide a callback for drag gestures , hope that flutter team will implement this feature soon.

Praseodymium answered 18/4, 2019 at 3:12 Comment(3)
I have opened up an official bug report on Github; github.com/flutter/flutter/issues/31243Polack
If you upvote the chances are higher they address the issue first.Polack
@tim done, please check my answer there it has a partial solutionPraseodymium
M
0

I think you should take a look at using a SliverFillRemaining or SliverFillViewport instead of SliverList. Heres an example using 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"),
        )
      ],
    );
  }
Millennial answered 16/1, 2019 at 15:43 Comment(5)
Thanks. That renders the WebView but the CustomScrollView seems to be consuming all the scroll events past the point where the AppBar scrolls off the screen. I'm sure there's a way to delegate the scroll events to the WebView at that point, but my flutter-fu is not up there. Going to try SliverFillViewport now.Merth
No luck with SilverFillViewport either. The WebView renders but when you scroll the WebView is duplicated past the point where the original WebView's bounds ended. I think, based on the docs, the SliverChildBuilderDelegate is called back once you go beyond the initial viewport to lazily create more children. What I see on the screen seems to suggest this is happening. So I am back where I was.Merth
Hmm might not be possible with a WebView then. I've been playing around with using a NestedScrollView instead of the CustomScrollView but can't get it to work. Theres a good example here if you want to have a play.Millennial
Did you find any solution to this?Polack
I tried the provided solution but it seems like the webview tries to resize when the appbar is scrolling out of view. Which makes it a really choppy/slow experience. I have a put a bounty on the question.Polack
H
0

After many trial and errors I found a way to fix a similar issue by using gestureRecognizers like so :

  @override
  Widget build(BuildContext context) {
    return SliverFillRemaining(
      child: WebView(
        initialUrl: url,
        javascriptMode: JavascriptMode.unrestricted,
        gestureRecognizers: {
          Factory<VerticalDragGestureRecognizer>(
            () => VerticalDragGestureRecognizer(),
          ),
        },
      ),
    );
  }
Hoy answered 6/9, 2022 at 14:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.