'Pull down to refresh WebView Page in flutter

I have created a flutter app with WebView

Is there any way to sweep down to refresh the webpage

I am using "webview_flutter_plugin" plugin

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Stack(
        children: <Widget>[
          Container(
            child: Center(
              child: Text(_title),
            ),
          ),
        ],
      )),
      body: SafeArea(
          child: WebView(
              key: _key,
              javascriptMode: JavascriptMode.unrestricted,
              initialUrl: _url)),
    );
  }
}


Solution 1:[1]

It's not easy to resolve but you can try this way.

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:fluttertoast/fluttertoast.dart';

int scheck;
WebViewController controllerGlobal;
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setEnabledSystemUIOverlays([]);
  runApp(
    new MaterialApp(
      debugShowCheckedModeBanner: false,
      home: new WebViewEx(),
    ),
  );
}

class WebViewEx extends StatefulWidget {
  @override
  WebViewExampleState createState() => WebViewExampleState();
}

class WebViewExampleState extends State<WebViewEx> {
  bool check, check1;
  ScrollController _scrollController;
  @override
  void initState() {
    _scrollController = ScrollController();
    _scrollController.addListener(_scrollListener);
    super.initState();
    check = false;
    check1 = false;
  }

  _scrollListener() {
    if (_scrollController.offset <=
            _scrollController.position.minScrollExtent &&
        !_scrollController.position.outOfRange) {
      controllerGlobal.reload();
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => controllerGlobal.goBack(),
      child: ListView(
        physics: ClampingScrollPhysics(),
        shrinkWrap: true,
        children: [
          Container(
            padding: EdgeInsets.all(10),
            height: MediaQuery.of(context).size.height,
            child: WebView(
              initialUrl: '...............',
              gestureNavigationEnabled: true,
              debuggingEnabled: true,
              gestureRecognizers: [
                Factory(() => PlatformViewVerticalGestureRecognizer()),
              ].toSet(),
              javascriptMode: JavascriptMode.unrestricted,
              onPageFinished: (String url) {
                setState(() {
                  bool temp = check;
                  check = true;
                  if (!temp) controllerGlobal.scrollBy(0, 10);
                });
              },
              onWebViewCreated: (WebViewController webViewController) {
                controllerGlobal = webViewController;
              },
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
  }
}

class PlatformViewVerticalGestureRecognizer
    extends VerticalDragGestureRecognizer {
  PlatformViewVerticalGestureRecognizer({PointerDeviceKind kind})
      : super(kind: kind);

  Offset _dragDistance = Offset.zero;

  @override
  void addPointer(PointerEvent event) {
    startTrackingPointer(event.pointer);
  }

  @override
  void handleEvent(PointerEvent event) {
    _dragDistance = _dragDistance + event.delta;
    controllerGlobal.getScrollY().then((value) {
      print(value);
      if (value < 5) {
        Fluttertoast.showToast(
            msg: "RELOADING",
            toastLength: Toast.LENGTH_SHORT,
            gravity: ToastGravity.BOTTOM,
            timeInSecForIosWeb: 1,
            backgroundColor: Colors.amber[800],
            textColor: Colors.black,
            fontSize: 16.0);
        controllerGlobal.reload();
      }
    });
    // if (event is PointerMoveEvent) {
    //   final double dy = _dragDistance.dy.abs();
    //   final double dx = _dragDistance.dx.abs();

    //   if (dy > dx && dy > kTouchSlop) {
    //     // vertical drag - accept
    //     resolve(GestureDisposition.accepted);
    //     _dragDistance = Offset.zero;
    //   } else if (dx > kTouchSlop && dx > dy) {
    //     // horizontal drag - stop tracking
    //     stopTrackingPointer(event.pointer);
    //     _dragDistance = Offset.zero;
    //   }
    // }
  }

  @override
  String get debugDescription => 'horizontal drag (platform view)';

  @override
  void didStopTrackingLastPointer(int pointer) {}
}

Solution 2:[2]

I Found Workaround for the webview pull to refresh using gesture recognizer just add the below code in your webview widget

WebView(
              key: UniqueKey(),
              initialUrl: 'https://summachar.app',
              javascriptMode: JavascriptMode.unrestricted,
              onWebViewCreated: (WebViewController webViewController) {
                _controller = webViewController;
              },
              onPageFinished: (String str) {
                myModel.stopLoading();
              },
              onPageStarted: (String str) {
                myModel.startLoading();
              },
              gestureRecognizers: Set()
                ..add(Factory<VerticalDragGestureRecognizer>(
                    () => VerticalDragGestureRecognizer()
                      ..onDown = (DragDownDetails dragDownDetails) {
                        _controller.getScrollY().then((value) {
                          if (value == 0 &&
                              dragDownDetails.globalPosition.direction < 1) {
                            _controller.reload();
                          }
                        });
                      })),
            ), 

Solution 3:[3]

Use flutter inAppWebView

flutter_inappwebview: ^5.0.5+2

Here is an example

late PullToRefreshController pullToRefreshController;
final MyInAppBrowser browser =  MyInAppBrowser();



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

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

InAppWebView(
                initialUrlRequest: URLRequest(
                    url: Uri.parse(widget.url)
                ),
                initialOptions: InAppWebViewGroupOptions(
                    crossPlatform: InAppWebViewOptions(

                    ),
                    ios: IOSInAppWebViewOptions(

                    ),
                    android: AndroidInAppWebViewOptions(
                        useHybridComposition: true
                    )
                ),
                onWebViewCreated: (InAppWebViewController controller) {
                  webView = controller;
                },
                onLoadStart: (controller, url) {
                  setState(() {
                    this.url = url?.toString() ?? '';
                  });
                },
                onLoadStop: (controller, url) async {
                  setState(() {
                    this.url = url?.toString() ?? '';
                  });
                },
                onProgressChanged: (controller, progress) {
                  setState(() {
                    this.progress = progress / 100;
                    if(progress == 100){
                      _isRefreshing = false;
                    }
                  });
                },
              ),

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sohaib Aslam
Solution 2 shalin shah
Solution 3 Chirag Kalathiya