pichillilorenzo / flutter_inappwebview

A Flutter plugin that allows you to add an inline webview, to use a headless webview, and to open an in-app browser window.
https://inappwebview.dev
Apache License 2.0
3.19k stars 1.57k forks source link

Can't scroll a large text inside webview both on Android and iOS #915

Open misici234 opened 3 years ago

misici234 commented 3 years ago

Environment

Technology Version
Flutter version Channel stable, 2.0.6, on Mac OS X 10.15.7 19H524 darwin-x64, locale en-CA
Plugin version 5.3.2
Android version 11
iOS version 14.4
Xcode version 12.4

Device information: iPhone 8 Apple

Description

I can't scroll a large text inside web view both on Android and iOS

Expected behavior: To be able to scroll.

Current behavior: I can't scroll a large text inside web view both on Android and iOS

Steps to reproduce

There is my source code in section Stacktrace. Line print('Can scroll vertically ${await webViewController.canScrollVertically()} and horizontally ${await webViewController.canScrollHorizontally()}'); prints Can scroll vertically false and horizontally false Why?

Images

Screen Shot 2021-07-15 at 10 27 33 AM

Stacktrace/Logcat

import 'dart:collection'; import 'dart:io';

import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';

import '../../constants.dart';

class AuraHtmlEditor extends StatefulWidget { final String title; final String initialContent; final bool isEditor;

AuraHtmlEditor(this.title, this.initialContent, [this.isEditor = true]);

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

class _AuraHtmlEditorState extends State { final GlobalKey webViewKey = GlobalKey();

InAppWebViewController webViewController;

InAppWebViewGroupOptions options = InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( useShouldOverrideUrlLoading: true, mediaPlaybackRequiresUserGesture: false, ), android: AndroidInAppWebViewOptions( useHybridComposition: true, cacheMode: AndroidCacheMode.LOAD_CACHE_ELSE_NETWORK, // NOTE: available on Android 24+. ), ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, ), );

PullToRefreshController pullToRefreshController; double loadProgress = 0.0; bool loadErrorOccurred = false;

String _processHtml(String auraHtml) { String txtIsi = auraHtml == null ? '' : auraHtml .replaceAll("'", r"\'") .replaceAll('"', r'\"') .replaceAll("[", r"[") .replaceAll("]", r"]") .replaceAll("\n", "
") .replaceAll("\n\n", "
") .replaceAll("\r", "") .replaceAll('\r\n', ""); return txtIsi; }

Future _getNoteBody({@required bool plain}) async { if (loadErrorOccurred) return '';

String note = await webViewController?.evaluateJavascript(source: 'getPlainText();');
print('Aura HTML editor plain content => "$note"');

if (note == '' || note == 'null' || note == '\n')
  note = '';
else if (!plain) {
  // set the real value of html note
  note = await webViewController?.evaluateJavascript(source: 'getHtml();');
}

print('From Aura HTML editor return => $note');

return note;

}

@override void initState() { super.initState();

pullToRefreshController = PullToRefreshController(
  options: PullToRefreshOptions(
    color: Colors.blue,
  ),
  onRefresh: () async {
    if (Platform.isAndroid) {
      webViewController?.reload();
    } else if (Platform.isIOS) {
      webViewController?.loadUrl(urlRequest: URLRequest(url: await webViewController?.getUrl()));
    }
  },
);

}

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(Platform.isAndroid ? Icons.arrow_back : Icons.arrow_back_ios), onPressed: () async { final result = AuraHtmlEditorResult( save: false, plainBody: await _getNoteBody(plain: true), htmlBody: await _getNoteBody(plain: false), );

        Navigator.of(context).pop(result);
      },
    ),
    automaticallyImplyLeading: false,
    title: Text(widget.title ?? ''),
    actions: [
      if (widget.isEditor)
        IconButton(
          icon: Icon(Icons.save),
          onPressed: () async {
            final result = AuraHtmlEditorResult(
              save: true,
              plainBody: await _getNoteBody(plain: true),
              htmlBody: await _getNoteBody(plain: false),
            );

            Navigator.of(context).pop(result);
          },
        ),
    ],
  ),
  body: SafeArea(
    // child: Stack(
    //   alignment: Alignment.center,
    //   children: [
    //     if (loadErrorOccurred)
    //       Center(
    //           child: Text(
    //         kHtmlEditorErrorMessage,
    //         textAlign: TextAlign.center,
    //       ))
    //     else
    child: InAppWebView(
      key: webViewKey,
      initialUrlRequest: URLRequest(
        url: Uri.parse("https://our_website_here"),
        iosCachePolicy: IOSURLRequestCachePolicy.RETURN_CACHE_DATA_ELSE_LOAD,
      ),
      initialUserScripts: UnmodifiableListView<UserScript>([]),
      initialOptions: options,
      pullToRefreshController: pullToRefreshController,
      onWebViewCreated: (controller) {
        webViewController = controller;
      },
      androidOnPermissionRequest: (controller, origin, resources) async {
        return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
      },
      onProgressChanged: (controller, progress) async {
        print('HTML editor/viewer loaded $progress %');

        setState(() => loadProgress = progress / 100);

        if (progress < 100) return;

        pullToRefreshController.endRefreshing();

        try {
          await webViewController?.evaluateJavascript(source: "setHtml('${_processHtml(widget.initialContent)}');");
          print('Can scroll vertically ${await webViewController.canScrollVertically()} and horizontally ${await webViewController.canScrollHorizontally()}');
        } catch (e) {
          print('Call to setHtml() Javascript failed due to: ' + e.toString());
        } finally {
          Future.delayed(Duration(milliseconds: 300), () async {
            // we have to delay execution of the following JS in order to set HTML data before we set
            // web site to read only mode
            // final scriptToRun = widget.isEditor ? "enableRTEControl();" : "disableRTEControl();";
            // await webViewController?.evaluateJavascript(source: scriptToRun);
          });
        }
      },
      onLoadError: (controller, url, code, message) {
        pullToRefreshController.endRefreshing();
        setState(() => loadErrorOccurred = true);
        print('Error $code occurred during HTML editor/viewer load: $message');
      },
      onConsoleMessage: (_, consoleMessage) {
        print('HTML editor/viewer console message ${consoleMessage.message}');
      },
      onScrollChanged: (_, x, y) {
        print('Scroll position x = $x , y = $y');
      },
    ),
    //   if (!loadErrorOccurred && loadProgress < 1.0) CircularProgressIndicator(),
    // ],
    // ),
  ),
);

} }

class AuraHtmlEditorResult { final bool save; final String plainBody; // TASK 9887 final String htmlBody; // TASK 9887

AuraHtmlEditorResult({ @required this.save, @required this.plainBody, @required this.htmlBody, }); }

github-actions[bot] commented 3 years ago

👋 @misici234

NOTE: This comment is auto-generated.

Are you sure you have already searched for the same problem?

Some people open new issues but they didn't search for something similar or for the same issue. Please, search for it using the GitHub issue search box or on the official inappwebview.dev website, or, also, using Google, StackOverflow, etc. before posting a new one. You may already find an answer to your problem!

If this is really a new issue, then thank you for raising it. I will investigate it and get back to you as soon as possible. Please, make sure you have given me as much context as possible! Also, if you didn't already, post a code example that can replicate this issue.

In the meantime, you can already search for some possible solutions online! Because this plugin uses native WebView, you can search online for the same issue adding android WebView [MY ERROR HERE] or ios WKWebView [MY ERROR HERE] keywords.

Following these steps can save you, me, and other people a lot of time, thanks!

misici234 commented 3 years ago

I finally found a solution in https://stackoverflow.com/questions/67345346/flutter-inappwebview-scroll-not-working-inside-the-nestedscrollview-tabbarview

InAppWebView(
gestureRecognizers: Set()..add(Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer())),
initialUrlRequest: URLRequest(url: Uri.parse("https://flutter.dev/"))),

The problem exists in Flutter 2.0.6 but as far as I remember it worked well in Flutter 1.??

I consider above solution just a workaround and would ask you to further investigate the root cause. Thanks.