Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SliverToNestedScrollBoxAdapter, webview disappear on keyboard input open #14

Open
JeanChristophePal opened this issue Aug 12, 2022 · 3 comments

Comments

@JeanChristophePal
Copy link

I'm using part of the code from the example
https://github.com/fluttercandies/extended_sliver/blob/master/example/lib/pages/nested/webview.dart

When I click on an editable field of the Webview, the complet view disappear, do you know why ?

import 'dart:io';
import 'dart:ui';

import 'package:extended_sliver/extended_sliver.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class NestedWebview extends StatelessWidget {
  NestedWebview({
    required this.url,
    Key? key,
  })  : nestedWebviewController = NestedWebviewController(url),
        super(key: key);

  final String url;
  final NestedWebviewController nestedWebviewController;

  final ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      primary: false,
      shrinkWrap: true,
      controller: scrollController,
      slivers: <Widget>[
        ValueListenableBuilder<double>(
          valueListenable: nestedWebviewController.scrollHeightNotifier,
          builder: (
            BuildContext context,
            double scrollHeight,
            Widget? child,
          ) {
            return SliverToNestedScrollBoxAdapter(
              childExtent: scrollHeight,
              onScrollOffsetChanged: (double scrollOffset) {
                double y = scrollOffset;
                if (Platform.isAndroid) {
                  // https://github.com/flutter/flutter/issues/75841
                  y *= window.devicePixelRatio;
                }
                nestedWebviewController.webviewController
                    ?.scrollTo(0, y.ceil());
              },
              child: child,
            );
          },
          child: WebView(
            initialUrl: nestedWebviewController.initialUrl,
            onPageStarted: nestedWebviewController.onPageStarted,
            onPageFinished: nestedWebviewController.onPageFinished,
            onWebResourceError: nestedWebviewController.onWebResourceError,
            onWebViewCreated: nestedWebviewController.onWebViewCreated,
            javascriptChannels: <JavascriptChannel>{
              nestedWebviewController.scrollHeightNotifierJavascriptChannel
            },
            javascriptMode: JavascriptMode.unrestricted,
          ),
        ),
      ],
    );
  }
}

class NestedWebviewController {
  NestedWebviewController(this.initialUrl);

  final String initialUrl;

  WebViewController? _webviewController;

  WebViewController? get webviewController => _webviewController;

  ValueNotifier<double> scrollHeightNotifier = ValueNotifier<double>(1);
  ValueNotifier<WebViewStatus> webViewStatusNotifier =
      ValueNotifier<WebViewStatus>(WebViewStatus.loading);

  void onWebViewCreated(WebViewController controller) {
    _webviewController = controller;
  }

  void onPageStarted(String url) {
    if (url == initialUrl ||
        webViewStatusNotifier.value == WebViewStatus.failed) {
      webViewStatusNotifier.value = WebViewStatus.loading;
    }
  }

  void onPageFinished(String url) {
    if (webViewStatusNotifier.value != WebViewStatus.failed) {
      _webviewController?.runJavascript(scrollHeightJs);
    }
  }

  void onWebResourceError(WebResourceError error) {
    webViewStatusNotifier.value = WebViewStatus.failed;
  }

  JavascriptChannel get scrollHeightNotifierJavascriptChannel =>
      JavascriptChannel(
        name: 'ScrollHeightNotifier',
        onMessageReceived: (JavascriptMessage message) {
          final String msg = message.message;
          final double? height = double.tryParse(msg);
          if (height != null) {
            scrollHeightNotifier.value = height;
            webViewStatusNotifier.value = WebViewStatus.completed;
          }
        },
      );
}

enum WebViewStatus {
  loading,
  failed,
  completed,
}

const String scrollHeightJs = '''(function() {
  var height = 0;
  var notifier = window.ScrollHeightNotifier || window.webkit.messageHandlers.ScrollHeightNotifier;
  if (!notifier) return;

  function checkAndNotify() {
    var curr = document.body.scrollHeight;
    if (curr !== height) {
      height = curr;
      notifier.postMessage(height.toString());
    }
  }

  var timer;
  var ob;
  if (window.ResizeObserver) {
    ob = new ResizeObserver(checkAndNotify);
    ob.observe(document.body);
  } else {
    timer = setTimeout(checkAndNotify, 200);
  }
  window.onbeforeunload = function() {
    ob && ob.disconnect();
    timer && clearTimeout(timer);
  };
})();''';
@zmtzawqlp
Copy link
Member

shrinkWrap: true, why need this

@JeanChristophePal
Copy link
Author

JeanChristophePal commented Aug 17, 2022

shrinkWrap: true, why need this

You are right this is not useful, I removed it.

I added resizeToAvoidBottomInset: false, to the parent Scaffold() is not totally working but it better. There is still some weird views:

Scaffold(
          resizeToAvoidBottomInset: false,
          body: NestedScrollView (
          ....
                body: NestedWebview(
                     url: 'https://www.qwant.com',
                );
          )

Simulator Screen Shot - iPhone SE (3rd generation) - 2022-08-17 at 13 56 15

@zmtzawqlp
Copy link
Member

runnable,simple demo,plz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants