How can i pull to refresh webview in flutter - android

I want to refresh webview page just when i swipe down the page. I found this code.
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:rivlus_webview_app/common_widgets/alert_dialog.dart';
class NewWebView extends StatefulWidget {
const NewWebView({Key? key}) : super(key: key);
#override
State<NewWebView> createState() => _NewWebViewState();
}
class _NewWebViewState extends State<NewWebView> {
WebViewController? _controller;
double progress = 0;
#override
Widget build(BuildContext context) {
return SafeArea(
child: WillPopScope(
onWillPop: () async {
final result = await const CommonAlertDialog(
title: 'Çıkış Yap',
content: 'Uygulamadan çıkış yapmak istediğinize emin misiniz?',
mainButtonText: 'Evet',
cancelButtonText: 'Vazgeç',
).show(context);
if (result == true) {
return exit(0);
} else {
return false;
}
},
child: WebView(
key: UniqueKey(),
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer()
..onDown = (DragDownDetails dragDownDetails) {
_controller!.getScrollY().then((value) {
if (value == 0 &&
dragDownDetails.globalPosition.direction < 1) {
_controller!.reload();
}
});
})),
),
),
);
}
}
This is work. But when I click on the top of the screen, it refreshes the page. I dont want this. I just want it to refresh the page when I pull the page down. How can I do that. Thanks.
Thanks for everyone. I solved this problem with inappwebview_flutter package.

I was facing this problem a lot while using web view the pull to refresh plugin is not working. Then I came across a solution that was very easy to use.
First declare a late variable of WebViewController:
late WebViewController webViewController;
Create WebView Widget and on it initialize webviewContoller in onWebViewCreated and use gestureRecognizers for pull to refresh:
WebView(
gestureNavigationEnabled: true,
initialUrl: 'yourwebsitelink',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated:
(WebViewController webViewController) {
this.webViewController = webViewController;
},
zoomEnabled: false,
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer()
..onDown = (DragDownDetails dragDownDetails) {
webViewController
.getScrollY()
.then((value) {
if (value == 0 &&
dragDownDetails
.globalPosition.direction <
1) {
webViewController.reload();
}
});
}
),
),
)
Hope this will solve your issue. Don't forget to give thanks.

you can use this plugin pull_to_refresh for swipe refresh.
onRefresh method of SmartRefresher

Related

'canGoBack' method isn't defined for flutter WebViewPlus

I'm trying to use ( canGoBack() ) method with (flutter webview plus) plugin but it isn't work!!
vs code said:
The method 'canGoBack' isn't defined for the type 'WebViewPlusController'.
Try correcting the name to the name of an existing method, or defining a method named 'canGoBack'.
this is my code:
//import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter_plus/webview_flutter_plus.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late WebViewPlusController controller;
#override
Widget build(BuildContext context) => WillPopScope (
onWillPop: () async {
if (await controller.canGoBack() ) {
return false; }
},
child: SafeArea(
child: Scaffold(
// ignore: avoid_unnecessary_containers
body: Container(
child: WebViewPlus(
initialUrl: 'assets/index.html',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) {
this.controller = controller;
},
),
),
),
),
);
}
how can I solve this problem?
I'm trying to use ( canGoBack() ) method with (flutter webview plus) plugin but it isn't work!!
To use the method canGoBack you have to access the WebViewPlusController's property webViewController, here an example:
if (await controller.webViewController.canGoBack()) {
return false;
}
More information in: https://pub.dev/documentation/webview_flutter_plus/latest/webview_flutter_plus/WebViewPlusController-class.html

Phone's Back Button doesn't work my WebView Flutter App, Any one to assist

I am trying to make my code work when phone's back button is tapped on a device(phone) the webview should be taken to the previous page, Now im having trouble getting the hardware back button to work. The app loads fine as does page and everything else but as soon as i hit the phones back button it crashes then forces close.
Here is my code
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewApp extends StatefulWidget {
#override
_WebViewAppState createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
//int _currentIndex = 0;
double opacity = 0.0;
#override
void initState() {
super.initState();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
#override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
toolbarHeight: 1,
),
body: Opacity(
opacity: opacity,
child: WebView(
initialUrl:
'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController controller) {
_controller.complete(controller);
},
onPageFinished: (_) {
setState(() {
opacity = 1.0;
});
}),
),
);
}
void onTabTapped(int index) {
setState(() {
//_currentIndex = index;
});
}
}
I do not have access to your stacktrace & I see that you are using webView.canGoBack() where I cannot see the webView variable.
Also, it is the _controller that handles the navigation like:
if (_controller.canGoBack()) _controller.goBack();
else super.onBackPressed();
More info. on the WebViewController: https://pub.dev/documentation/webview_flutter/latest/webview_flutter/WebViewController-class.html

i am facing flutter webview issue

I am new in a flutter. I m facing an issue in flutter_webview here is my code IDK what's wrong with it. I write this code with the help of StackOverflow and an official plugin. my HTML files working fine
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
class Licences extends StatefulWidget {
#override
_LicencesState createState() => _LicencesState();
}
class _LicencesState extends State<Licences> {
WebViewController webViewController;
String filePath = 'files/PrivacyPolicy.html';
loadHtml() async {
String data = await rootBundle.loadString(filePath);
webViewController.loadUrl(Uri.dataFromString(data,
mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
.toString());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Open-Source Licences'),
),
body: Builder(builder: (BuildContext context) {
return WebView(
initialUrl: '',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController controller) {
webViewController = controller;
loadHtml();
},
);
}),
);
}
}

How to implement progress Indicator in web view for every page load flutter?

I am currently showing progress indicator before webview load using this code:
My Full main.dart code:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
//import 'package:mtcl/utils/AppColors.dart';
import 'package:custom_splash/custom_splash.dart';
import 'package:connectivity/connectivity.dart';
void main() {
//runApp(MyApp());
//var result = Connectivity().checkConnectivity();
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
// if (result == ConnectivityResult.none) {
// WidgetsFlutterBinding.ensureInitialized();
// runApp(MyApp());
// } else if (result == ConnectivityResult.mobile) {
// WidgetsFlutterBinding.ensureInitialized();
// runApp(MyApp());
// } else if (result == ConnectivityResult.wifi) {
// WidgetsFlutterBinding.ensureInitialized();
// runApp(MyApp());
// }
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "MTCL Client",
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.red,
),
home: Scaffold(body: splash()));
}
}
class splash extends StatefulWidget {
#override
_splashState createState() => _splashState();
}
class _splashState extends State<splash> {
#override
Widget build(BuildContext context) {
return CustomSplash(
backGroundColor: Color(0xFFFF9800),
imagePath: "assets/images/logo.png",
home: WebViewClass(),
duration: 10,
animationEffect: "zoom-in",
);
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> {
num position = 1;
final key = UniqueKey();
doneLoading(String A) {
setState(() {
position = 0;
});
}
startLoading(String A) {
setState(() {
position = 1;
});
}
//Check Internet Code Starts
//Check Internet Code Ended here
#override
Widget build(BuildContext context) {
return Scaffold(
//appBar: AppBar(title: Text('Show ProgressBar While Loading Webview')),
appBar: PreferredSize(
child: Container(),
preferredSize: Size.fromHeight(0.0),
),
body: IndexedStack(index: position, children: <Widget>[
WebView(
initialUrl: 'http://110.38.4.4/login/client',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageFinished: doneLoading,
onPageStarted: startLoading,
),
Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.red),
)),
),
]));
}
}
Now what I need is to show the progress indicator instantly for every action like If the user clicks on login button after filling login credential, I want the progress indicator to be shown instantly after clicking the button while now the progress indicator is showing after a few moments of button click. How can I achieve such thing in flutter?
You can add your code that triggers the progress indicator inside navigationDelegate:
WebView(
initialUrl: 'https://flutter.dev',
navigationDelegate: (NavigationRequest request) {
print('Navigating to ${request.url}');
// Call any code here that you want
return NavigationDecision.navigate;
},
),
Based on navigationDelegate as suggested by Soares , this is my full working code
class _WikipediaExplorerState extends State<WikipediaExplorer> {
Completer<WebViewController> _controller = Completer<WebViewController>();
final Set<String> _favorites = Set<String>();
String title, url;
bool isLoading = true;
final _key = UniqueKey();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Facebook Test Webview'),
// This drop down menu demonstrates that Flutter widgets can be shown over the web view.
actions: <Widget>[
NavigationControls(_controller.future),
Menu(_controller.future, () => _favorites),
],
),
body: Builder(builder: (BuildContext context) {
return Stack(
children: <Widget>[
WebView(
initialUrl: 'https://www.facebook.com/',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
// TODO(iskakaushik): Remove this when collection literals makes it to stable.
// ignore: prefer_collection_literals
javascriptChannels: <JavascriptChannel>[
_toasterJavascriptChannel(context),
].toSet(),
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
print('allowing navigation to $request');
setState(() {
isLoading = true;
});
return NavigationDecision.navigate;
},
onPageFinished: (String url) {
print('Page finished loading: $url');
setState(() {
isLoading = false;
});
},
),
isLoading
? Center(
child: CircularProgressIndicator(),
)
: Stack(),
],
);
}),
);
}
}
Every time a new link is clicked within the app, a circular progress dialog will be initiated

How to Make Customize Error Page in Webview Flutter

I am new to flutter. Currently i am building the web app that using flutter webview plugin but i have a question about the internet connectivity. When users doesnt have a connection that app gives a default error page like
Webpage not available
The webpage at https://covid19.who.int/ could be not be loaded because:
net:::ERR_Internet_disconnected
How to use custom code to show custom error page like to hide url? My proper code is:
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:covidwho/layout/myAppBar.dart';
class Who extends StatefulWidget {
#override
_WhoState createState() => _WhoState();
}
class _WhoState extends State<Who> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppBar(),
body: Container(
child: WebviewScaffold(
url: "https://covid19.who.int/",
withJavascript: true,
withLocalStorage: true,
hidden: true,
initialChild: Container(
color: Colors.white,
child: const Center(
child: CircularProgressIndicator(
backgroundColor: Colors.black,
),
)),
),
),
);
}
}
I would like to share with you the code I use to show custom pages at the time of flutter web errors.
Full project link https://github.com/K3rimoff/flutter-custom-web-error-page
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import '../../components/back_pressed.dart';
import '../../theme/colors.dart';
import '../error/error.dart';
class WebScreen extends StatefulWidget {
const WebScreen({super.key});
#override
State<WebScreen> createState() => _WebScreenState();
}
class _WebScreenState extends State<WebScreen> with TickerProviderStateMixin {
late AnimationController _animationController;
InAppWebViewController? _webViewController;
PullToRefreshController? _refreshController;
bool _isLoading = false, _isVisible = false, _isOffline = false;
// 0 - Everything is ok, 1 - http or other error fixed
int _errorCode = 0;
final BackPressed _backPressed = BackPressed();
Future<void> checkError() async {
//Hide CircularProgressIndicator
_isLoading = false;
//Check Network Status
ConnectivityResult result = await Connectivity().checkConnectivity();
//if Online: hide offline page and show web page
if (result != ConnectivityResult.none) {
if (_isOffline == true) {
_isVisible = false; //Hide Offline Page
_isOffline = false; //set Page type to error
}
}
//If Offline: hide web page show offline page
else {
_errorCode = 0;
_isOffline = true; //Set Page type to offline
_isVisible = true; //Show offline page
}
// If error is fixed: hide error page and show web page
if (_errorCode == 1) _isVisible = false;
setState(() {});
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 2));
_animationController.repeat();
_refreshController = PullToRefreshController(
onRefresh: () => _webViewController!.reload(),
options: PullToRefreshOptions(
color: Colors.white, backgroundColor: Colors.black87),
);
}
#override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(
body: SafeArea(
child: Stack(
alignment: Alignment.center,
children: [
InAppWebView(
onWebViewCreated: (controller) =>
_webViewController = controller,
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
supportZoom: false,
)),
initialUrlRequest: URLRequest(
url: Uri.parse(
"https://google.com")), // For http error: change to wrong url : https://google.com/404/
pullToRefreshController: _refreshController,
onLoadStart: (controller, url) {
setState(() {
_isLoading = true; //Show CircularProgressIndicator
});
},
onLoadStop: (controller, url) {
_refreshController!.endRefreshing();
checkError(); //Check Error type: offline or other error
},
onLoadError: (controller, url, code, message) {
// Show
_errorCode = code;
_isVisible = true;
},
onLoadHttpError: (controller, url, statusCode, description) {
_errorCode = statusCode;
_isVisible = true;
},
),
//Error Page
Visibility(
visible: _isVisible,
child: ErrorScreen(
isOffline: _isOffline,
onPressed: () {
_webViewController!.reload();
if (_errorCode != 0) {
_errorCode = 1;
}
}),
),
//CircularProgressIndicator
Visibility(
visible: _isLoading,
child: CircularProgressIndicator.adaptive(
valueColor: _animationController.drive(
ColorTween(
begin: circularProgressBegin,
end: circularProgressEnd),
),
),
),
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton.icon(
onPressed: () {
_errorCode = 1;//My Error fixed code
_webViewController!.loadUrl(
urlRequest: URLRequest(
url: Uri.parse("https://google.com/"), //Correct url
),
);
},
label: const Text("Load Correct URL"),
icon: const Icon(Icons.check),
),
ElevatedButton.icon(
onPressed: () {
_webViewController!.loadUrl(
urlRequest: URLRequest(
url: Uri.parse("https://google.com/404"), //Wrong url
),
);
},
label: const Text("Load Wrong URL"),
icon: const Icon(Icons.close),
),
],
),
),
onWillPop: () async {
//If website can go back page
if (await _webViewController!.canGoBack()) {
await _webViewController!.goBack();
return false;
} else {
//Double pressed to exit app
return _backPressed.exit(context);
}
});
}
}
For that you need to implement
Stream<String> onError webview event.
Don't forget to dispose webview flutterWebviewPlugin.dispose()
Here is a code sample
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
String selectedUrl = 'https://flutter.io';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyHomePage());
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Instance of WebView plugin
final flutterWebViewPlugin = FlutterWebviewPlugin();
// On destroy stream
StreamSubscription _onDestroy;
// On Http error
StreamSubscription<WebViewHttpError> _onHttpError;
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
flutterWebViewPlugin.launch(selectedUrl);
// Add a listener to on destroy WebView, so you can make came actions.
_onDestroy = flutterWebViewPlugin.onDestroy.listen((_) {
if (mounted) {
// Actions like show a info toast.
_scaffoldKey.currentState.showSnackBar(
const SnackBar(content: const Text('Webview Destroyed')));
}
});
_onHttpError =
flutterWebViewPlugin.onHttpError.listen((WebViewHttpError error) {
if (mounted) {
//do your customization here
}
});
}
#override
void dispose() {
// Every listener should be canceled, the same should be done with this stream.
_onDestroy.cancel();
_onHttpError.cancel();
flutterWebViewPlugin.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
);
}
}

Categories

Resources