How to add CircularProgressIndicator when loading web page using flutter_inappwebview? - flutter

I am new in flutter,
I tried to add a CircularProgressIndicator while waiting to the web page to load,
and then the page display and the circular indicator dosen't show on screen.
where it's should be? maybe in onLoadStart function below?
Source code:
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class CoursesInformation extends StatefulWidget {
#override
_CoursesInformationState createState() => _CoursesInformationState();
}
class _CoursesInformationState extends State<CoursesInformation> {
InAppWebViewController webView;
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: AppBar(
title: const Text('מידע על קורסים'),
centerTitle: true,
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: InAppWebView(
initialUrl:
"https://shoham.biu.ac.il/BiuCoursesViewer/MainPage.aspx",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
preferredContentMode: UserPreferredContentMode.DESKTOP),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) async {
},
))
])),
),
);
}
}

You can onProgressChanged parameter and show the loader. You can also use LinearProgressIndicator (check commented code). Check the following example
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
void main() {
// it should be the first line in main method
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark()
.copyWith(scaffoldBackgroundColor: Color.fromARGB(255, 18, 32, 47)),
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(body: CustomPage());
}
}
class CustomPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return CustomPageState();
}
}
class CustomPageState extends State<CustomPage> {
InAppWebViewController webView;
double progress = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('מידע על קורסים'),
centerTitle: true,
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: InAppWebView(
initialUrl:
"https://shoham.biu.ac.il/BiuCoursesViewer/MainPage.aspx",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
preferredContentMode: UserPreferredContentMode.DESKTOP),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop:
(InAppWebViewController controller, String url) async {
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
),
),
Align(
alignment: Alignment.center,
child: _buildProgressBar()
),
],
))
])),
);
}
Widget _buildProgressBar() {
if (progress != 1.0) {
return CircularProgressIndicator();
// You can use LinearProgressIndicator also
// return LinearProgressIndicator(
// value: progress,
// valueColor: new AlwaysStoppedAnimation<Color>(Colors.orange),
// backgroundColor: Colors.blue,
// );
}
return Container();
}
}

Related

Web view doesn't show the web page in Flutter application

I have this code in my flutter app :
class WebViewWidget1 extends StatefulWidget {
WebViewWidget1({Key? key}) : super(key: key);
#override
State<WebViewWidget1> createState() => _WebViewWidget1State();
}
class _WebViewWidget1State extends State<WebViewWidget1> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('title'),
),
body: const WebView(
initialUrl: "https://github.com/ArjunMalhotra07",
javascriptMode: JavascriptMode.unrestricted,
),
);
}
}
I want to implement web view and this was the code I took from the internet. This just doesn't work. It shows a blank white screen with app bar only. Where am I wrong? can't deduce.
please add pubspec.yaml
flutter pub add flutter_inappwebview
inappwebview
Example:
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class InAppWebViewPage extends StatefulWidget {
final String title, uri;
const InAppWebViewPage({Key? key, required this.title, required this.uri})
: super(key: key);
#override
_InAppWebViewPageState createState() => _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
int _stackIndex = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: EdgeInsets.all(12),
child: Expanded(
child: IndexedStack(
index: _stackIndex,
children: [
InAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse(widget.uri)),
initialOptions: InAppWebViewGroupOptions(
crossPlatform:
InAppWebViewOptions(useShouldOverrideUrlLoading: true),
),
onLoadStop: (_, __) {
setState(() {
_stackIndex = 0;
});
},
onLoadError: (_, __, ___, ____) {
setState(() {
_stackIndex = 0;
});
//TODO: Show error alert message (Error in receive data from server)
},
onLoadHttpError: (_, __, ___, ____) {
setState(() {
_stackIndex = 0;
});
//TODO: Show error alert message (Error in receive data from server)
},
),
const SizedBox(
height: 50,
child: CircularProgressIndicator(),
),
],
),
),
),
);
}
}
Try to wrap WebView with SizedBox and give width and height to it.
SizedBox(
width: MediaQuery.of(context).size.width, // it uses all the width of screen, you can change it
height: MediaQuery.of(context).size.height, // it uses all the height of screen, you can change it
child: WebView(
initialUrl: "https://github.com/ArjunMalhotra07",
javascriptMode: JavascriptMode.unrestricted,
),
),
And don't forget to add webview_flutter package to your pubspec.yaml file.

How to show Loading Indicator background transparent in WebView Flutter?

I'm new to flutter and making my first webview app. Here I'm trying to add a spinner every time when a user tries to click the link or page load. I want to make spinner background opacity a bit low just like the given example(right picture) but opacity doesn't work at all.
Here is my approach:
// ignore_for_file: prefer_const_constructors
// ignore: use_key_in_widget_constructors
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: WebViewClass()
)
);
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass>{
int position = 1 ;
final key = UniqueKey();
doneLoading(String A) {
setState(() {
position = 0;
});
}
startLoading(String A){
setState(() {
position = 1;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: SafeArea(child: IndexedStack(
index: position,
children: <Widget>[
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key ,
onPageFinished: doneLoading,
onPageStarted: startLoading,
),
Container(
color: Colors.white70,
child: Center(
child: CircularProgressIndicator()),
),
]))
);
}
}
Any help or guidance will highly appreciated.
You can try like this. every time when you come in the web view screen. the loader will show.
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> {
bool isLoading = false;
final key = UniqueKey();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: SafeArea(
child: IgnorePointer(
ignoring: isLoading,
child: Stack(
children: [
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageFinished: (value) {
setState(() {
isLoading = false;
});
},
onPageStarted: (value) {
setState(() {
isLoading = true;
});
},
),
isLoading ? Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.grey.withOpacity(0.5),
child: const Center(child: CircularProgressIndicator()) ,
) : Container(),
],
),
)),);
}
}

Android crashes when I try to use qr scanning with a web view

I try to use a QR Code Scanner from qr_code_scanner in conjunction with a Webview component webview_flutter.
Everything works fine on iOS but on Android devices it doesn't work, the QR scanner doesn't show and I get a repeated console print.
D/mali_winsys(30667): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
I've tried this on two Android devices (Android 10, v29 and Android 7, v24) with same results.
Below is a minimal app that reproduce the issue. It requires the following dependencies:
qr_code_scanner: ^0.3.5
webview_flutter: ^2.0.2
The code below shows a full-screen webview with a button on-top. Press the button and the QR scanner will/should show up...
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showQr = false;
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
void closeQr() {
setState(() {
_showQr = false;
});
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Stack(
children: [
WebView(
initialUrl: 'https://flutter.dev',
),
Center(
child: TextButton(
onPressed: () {
setState(() {
_showQr = !_showQr;
});
},
child: Text('Show QR Scanner'),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.teal,
onSurface: Colors.grey,
),
),
),
],
),
Center(
child: (_showQr) ? QRWidget(onClose: closeQr) : null,
),
],
);
}
}
class QRWidget extends StatefulWidget {
const QRWidget({
Key key,
this.onClose,
}) : super(key: key);
final Function onClose;
#override
State<StatefulWidget> createState() => _QRWidgetState();
}
class _QRWidgetState extends State<QRWidget> {
Barcode result;
QRViewController controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller.pauseCamera();
}
controller.resumeCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
_buildQrView(context),
Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.only(bottom: 60.0),
child: Row(
children: <Widget>[
Expanded(
child: RawMaterialButton(
onPressed: () {
setState(() {
widget.onClose();
});
},
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.close_sharp,
color: Color(0xff459d44),
size: 40.0,
),
padding: EdgeInsets.all(8.0),
shape: CircleBorder(),
),
),
],
),
)
],
),
);
}
Widget _buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Color(0xff459d44),
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}
Why doesn't it work on Android?
did you add the permission in AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
if its webview, why dont you use flutter_inappwebview . Its good to use and has a lot of additional features you may want later. it still needs permission on androidmanifest. Following is the example if you decide to choose flutter_inappwebview.
class _HomePageState extends State<HomePage> {
InAppWebViewController webView;
String url = "";
#override
void initState(){
checkPermissions();
super.initState();
}
#override
void dispose() {
super.dispose();
}
checkPermissions() async{
await [
Permission.camera,
Permission.storage,
].request();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: 'https://flutter.dev',
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
/// this is the important one to pass the permission
androidOnPermissionRequest: (InAppWebViewController controller, String origin, List<String> resources) async {
return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
},
),
),
),
])
),
),
);
}
}
dont forget to add this permission_handler in your pubspec.yaml

Flutter give camera and microphone permissions after pressing button or on onpressed event

I have a requirement to give Camera and Microphone permissions on the click of a button. I want my permissions to appear one after another but in this case, only microphone permission appears. To give permission for Camera I have to again press the button.
How can I achieve this?
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
class IframeScreen extends StatefulWidget {
#override
_IframeScreenState createState() => _IframeScreenState();
}
class _IframeScreenState extends State<IframeScreen> {
InAppWebViewController _webViewController;
Future webViewMethod() async {
print('In Microphone permission method');
WidgetsFlutterBinding.ensureInitialized();
Permission.microphone.request();
WebViewMethodForCamera();
}
Future WebViewMethodForCamera() async{
print('In Camera permission method');
WidgetsFlutterBinding.ensureInitialized();
Permission.camera.request();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Check this frame'),
),
body: Column(
children: <Widget>[
RaisedButton(
onPressed: webViewMethod,
child: Text('Join'),
textColor: Colors.black,
),
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://appr.tc/r/158489234",
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
mediaPlaybackRequiresUserGesture: false,
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
androidOnPermissionRequest: (
InAppWebViewController controller, String origin,
List<String> resources) async {
return PermissionRequestResponse(resources: resources,
action: PermissionRequestResponseAction.GRANT);
}
),
),
)
],
)
);
}
}
You can copy paste run full code below
You can await Permission.microphone.request(); and await Permission.camera.request();
code snippet
Future webViewMethod() async {
print('In Microphone permission method');
//WidgetsFlutterBinding.ensureInitialized();
await Permission.microphone.request();
WebViewMethodForCamera();
}
Future WebViewMethodForCamera() async{
print('In Camera permission method');
//WidgetsFlutterBinding.ensureInitialized();
await Permission.camera.request();
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
class IframeScreen extends StatefulWidget {
#override
_IframeScreenState createState() => _IframeScreenState();
}
class _IframeScreenState extends State<IframeScreen> {
InAppWebViewController _webViewController;
Future webViewMethod() async {
print('In Microphone permission method');
//WidgetsFlutterBinding.ensureInitialized();
await Permission.microphone.request();
WebViewMethodForCamera();
}
Future WebViewMethodForCamera() async{
print('In Camera permission method');
//WidgetsFlutterBinding.ensureInitialized();
await Permission.camera.request();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Check this frame'),
),
body: Column(
children: <Widget>[
RaisedButton(
onPressed: webViewMethod,
child: Text('Join'),
textColor: Colors.black,
),
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://appr.tc/r/158489234",
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
mediaPlaybackRequiresUserGesture: false,
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
androidOnPermissionRequest: (
InAppWebViewController controller, String origin,
List<String> resources) async {
return PermissionRequestResponse(resources: resources,
action: PermissionRequestResponseAction.GRANT);
}
),
),
)
],
)
);
} }
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: IframeScreen(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Trying
await WebViewMethodForCamera();

Flutter load webview inside the fragment

// Here is my flutter code
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
class HairtipsPage extends StatefulWidget {
#override
_HairtipsPageState createState() => _HairtipsPageState();
}
class _HairtipsPageState extends State<HairtipsPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child : WebviewScaffold(
url: "https://www.google.com",
appBar: new AppBar(
// title: new Text('Hairtips'),
),
withZoom: true,
withLocalStorage: true,
)
),
);
}
}
I am using bottom navigation in my app and trying to implement webview inside the fragment.i know how to acheive the same in android also i dont want the webview should open in a browser.i am expecting the webview should load inside the app and within the fragment.
You can use the Flutter webview plugin. Here is the URL for the plugin https://pub.dartlang.org/packages/webview_flutter
The webview will load inside the App with CircularProgressIndicator.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebView extends StatefulWidget {
#override
_WebViewState createState() => _WebViewState();
}
class _WebViewState extends State<WebView> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
num _stackToView = 1;
void _handleLoad(String value) {
setState(() {
_stackToView = 0;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(builder: (BuildContext context) {
return IconButton(
icon: Icon(Icons.volume_up, color: Colors.black,),
onPressed: () {
Navigator.pop(context);
},
);
}),
backgroundColor: Colors.white10,
elevation: 0,
),
body: IndexedStack(
index: _stackToView,
children: [
Column(
children: <Widget>[
Expanded(
child: WebView(
initialUrl: "https://www.google.co.in/",
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: _handleLoad,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
)),
],
),
Container(
child: Center(child: CircularProgressIndicator(),)
),
],
));
}
}