Flutter - How to turn off youtube video in webview after back event? - dart

So i just implemented this WebView in flutter and it's great, but there's a problem when i embedd a youtube video using webview, the video is still playing even i close the Webview page. How do i turn it off?
the plugin that i use is flutter_webview_plugin
final flutterWebviewPlugin =FlutterWebviewPlugin();
#override
void initState() {
super.initState();
flutterWebviewPlugin.close();
}
#override
void dispose() {
super.dispose();
flutterWebviewPlugin.dispose();
}
and this is the widget:
IconButton(
icon: Icon(Icons.more_vert),
onPressed: () {
print('Hello there!'); flutterWebviewPlugin.launch('https://www.youtube.com/embed/m5rm8ac4Gsc');
},
)

What you can do is to create a route and but inside it your webview example: /youtubeWebview and use Navigator.popAndPushNamed(context, '/yourRoute'); to go back instead of Navigator.pop(context);

I finally get the answer but i change the package to webview_flutter instead of flutter_webview_plugin.
To stop the audio from youtube or any other website that has audio we need to change the url of the current webview. and maybe it will work with flutter_webview_plugin too.
/* define webview controller */
WebViewController _controller;
/* before we leave current route, make sure to change the url to something */
Future<bool> _willPopCallback(WebViewController controller) async {
controller.loadUrl('https://www.google.com/'); /* or you can use controller.reload() to just reload the page */
return true;
}
return WillPopScope(
onWillPop: () => _willPopCallback(_controller), /* call the function here */
child: Scaffold(
appBar: AppBar(
title: Text('Just appbar'),
),
body: Column(
children: <Widget>[
Expanded(
child: WebView(
key: UniqueKey(),
javascriptMode: JavascriptMode.unrestricted,
initialUrl: widget.videoUrl,
onWebViewCreated: (WebViewController webViewController) { /* i am not sure what this line actually do */
_controller = webViewController;
},
),
),
Text(
'Please pause the video before you go back',
style: TextStyle(
color: Colors.black,
),
)
],
),
),
);

Related

Flutter video_player replaying video loaded from assets

I am trying using the video_player package to try and load, play, and then replay a video from assets. The video loads correctly and plays fine on the first run through. However when I try to replay the video using _controller.seekTo(Duration.zero) and _controller.play() it remains frozen on the last frame of the video and won't replay back.
This occurs only in iOS but not in Android where it behaves as expected. And it only occurs for videos loaded from assets. If I load a video from a url using VideoPlayerController.network it also behaves as expected.
Below is the class I modified from the video_player example.
import 'package:video_player/video_player.dart';
import 'package:flutter/material.dart';
class VideoApp extends StatefulWidget {
#override
_VideoAppState createState() => _VideoAppState();
}
class _VideoAppState extends State<VideoApp> {
VideoPlayerController _controller;
#override
void initState() {
super.initState();
_controller = VideoPlayerController.asset('assets/video/MOV_GET_OUT_BED.mp4')
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Demo',
home: Scaffold(
body: Column(
children: <Widget>[
Center(
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
GestureDetector(
onTap: () async {
await _controller.seekTo(Duration.zero);
setState( () {
_controller.play();
} );
},
child: Text("Restart video")
),
]
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
To auto replay, add this to your initState() method.
_controller.setLooping(true);

How to update webview's url on setState flutter?

I need to update webview's url with my setState. How to do that?
The initial url I haved set on constructor have been loaded successfully. But it's not working when I try load the new one through my drawer menu by onTap method.
...
class _MyWebState extends State<MyWeb> {
Completer<WebViewController> _controller = Completer<WebViewController>();
final Set<String> _favorites = Set<String>();
String url;
Widget web;
_MyWebState() {
web = WebView(
initialUrl: 'https://my.flazhost.com',
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('MyWeb'),
actions: <Widget>[
NavigationControls(_controller.future),
Menu(_controller.future, () => _favorites),
],
),
body: web,
drawer: Drawer(
child: ListView(
children: <Widget>[
ListTile(
leading: FlutterLogo(
size: 20,
),
title: Text('Web AlQudwah'),
onTap: () {
setState(() {
web = WebView(
initialUrl: 'https://flazhost.com',
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
);
Navigator.pop(context);
});
},
),
],
),
),
floatingActionButton: _bookmarkButton(),
);
}
}
...
How to update webview's url onTap method? Please help?
I struggled with the flutter webview for a long time, and I'm still not very happy with it...
But the key is the WebController instance that you get from the onWebViewCreated method of the webview. The instance of the initialized WebViewController has a method called loadUrl('your_new_url')
So you can just call following in your onTap handler:
onTap: () {
_controller.loadUrl('your_new_url');
}
When working with WebViews in flutter I experienced problems when using setState, because it will trigger a rebuild of whole page including the webview which gets reinitialized and of course reloads the page...
But that is mostly not the desired result, so if you want to controll the webview (wheater it will be changes to url, going back in browser history or executing javascript) you should handle it over the WebController initialized from the onWebViewCreated method
Here are the most used methods of the WebViewController class:
_controller.currentUrl() // Gets current url from WebView
_controller.loadUrl('your_new_url'); // Loads new url
_controller.evaluateJavascript('your js code as a string') // Execute JS over WebView console
_controller.goBack() // Goes one step back in browser history
_controller.goForward() // Goes one step forwards in browser history
_controller.clearCache() // Clears cache of WebView
It's really confusing and badly documented (espacially for beginners like me), so I hope the flutter team will provide us with more detailed information and tutorials

how to download/create pdf through webview in flutter

I have created a webviewscaffold but can't download anything from it while browsing from the webview, I made but when I click the button it does nothing. I don't know where to start, like in other browsers that can download and preview, I'm trying to achieve the same thing in here.
class AppState extends State<App> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Align(
alignment: Alignment(1, 1),
child: Container(
child: Web(), // it is a statefulwidget that have WebviewScaffold, i have created it on a new page and imported/used here
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 20.0),
)
],
),
Align(
alignment: Alignment(0.7, -0.93),
child: FloatingActionButton(
tooltip: "Share",
child: Icon(
Icons.share,
color: Colors.amberAccent,
),
onPressed: () {
_onShareTap();
}),
),
],
),
);
}
I expect, when I click the print or download button within the webview it should work like any other browser.
You can use my plugin flutter_inappwebview, which is a Flutter plugin that allows you to add inline WebViews or open an in-app browser window and has a lot of events, methods, and options to control WebViews.
To be able to recognize downloadable files, you need to set the useOnDownloadStart: true option, and then you can listen the onDownloadStart event!
Also, for example, on Android you need to add write permission inside your AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Then, you need to ask permission using the permission_handler plugin. Instead, to effectively download your file, you can use the flutter_downloader plugin.
Here is a complete example using http://ovh.net/files/ (in particular, the http://ovh.net/files/1Mio.dat as URL) to test the download:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await FlutterDownloader.initialize(
debug: true // optional: set false to disable printing logs to console
);
await Permission.storage.request();
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
InAppWebViewController webView;
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('InAppWebView Example'),
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: InAppWebView(
initialUrl: "http://ovh.net/files/1Mio.dat",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
useOnDownloadStart: true
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
onDownloadStart: (controller, url) async {
print("onDownloadStart $url");
final taskId = await FlutterDownloader.enqueue(
url: url,
savedDir: (await getExternalStorageDirectory()).path,
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
},
))
])),
),
);
}
}
Here, as you can see, I'm using also the path_provider plugin to get the folder where I want to save the file.
If you are the owner of html page, you can check workaround that works for me. In source of your html page add onclick function for specific resource links:
function downloadpdf() {
var currentHref = window.location.href;
window.history.pushState(null, null, '/app/somepdf.pdf');
setTimeout(() => window.location.replace(currentHref), 1000);
}
In Flutter code add listener:
StreamSubscription<String> _onWebViewUrlChanged;
_onWebViewUrlChanged =
FlutterWebviewPlugin().onUrlChanged.listen((String url) {
if (url.contains('.pdf')) {
launchURL(url);
}
});
launchURL will open predefined url in external browser window. So you can download pdf/etc from flutter_webview_plugin.
You should add some your app-specific js/flutter magic

Flutter - Navigator doesn't return back (Black screen)

I'm new on flutter, I have a Homepage where I have a Drawer menu and body list content.
DRAWER MENU => On tap item list of drawer menu I'm loading a PAGE web URL and on tap BACK it returns to my homepage. So it works very well.
BODY LIST CONTENT => On tap item list it loads the page web URL well BUT when I won't return back to my homepage it returns a black screen :(
Homepage.dart
class HomePage extends StatefulWidget{
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomePage();
}
}
class _HomePage extends State<HomePage>{
#override
Widget build(BuildContext context) {
// TODO: implement build
var globalContext = context;
return Scaffold(
appBar: AppBar(
title: Text(
'Benvenuto',
style: TextStyle(color: Colors.white)
),
backgroundColor: Color(0xFF4035b1),
),
drawer: Drawer(
child: new Column(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: Text('VIA ALBERTO POLIO 54'),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF4268D3),
Color(0xFF584CD1)
],
begin: FractionalOffset(0.2, 0.0),
end: FractionalOffset(1.0, 0.6),
stops: [0.0, 0.6],
tileMode: TileMode.clamp
)
),
accountEmail: Text('ORARI: LUNEDI - VENERDI 9:30 / 19:30'),
currentAccountPicture: new CircleAvatar(
radius: 50.0,
backgroundColor: const Color(0xFF778899),
backgroundImage: AssetImage("assets/img/icon_logo.jpg"),
)
),
// This list work well!
ListTile(
leading: new Icon(Icons.arrow_forward_ios),
title: new Text("TEST"),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => Page("title", "www.google.com")));
}
)
],
),
),
// The menu on my body load well the page web url but doesn't return back to my homepage.
body: new Column(
children: <Widget>[
ListTile(
leading: new Icon(Icons.arrow_forward_ios),
title: new Text("TEST"),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => Page("title", "www.google.com")));
}
)
])
);
}
}
Page.dart
class Page extends StatelessWidget{
final String titleText;
final String urlSource;
Page(this.titleText, this.urlSource);
#override
Widget build(BuildContext context) {
// TODO: implement build
return new WebviewScaffold(
url: urlSource,
appBar: new AppBar(
title: Text(titleText),
),
withZoom: true,
withLocalStorage: true,
hidden: true,
);
}
}
main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: HomePage()
);
}
}
Thank you for your help guys!
You shouldn't be using Navigator.pop() just before Navigator.push().
If replacing the current page with a new one is what you want, you can use Navigator.of(context).pushReplacement().
If you only want to navigate to a new route delete the pop method and only use push
The real problem here is that when you're using Navigator.pop() you're removing it from the "pages stack". When you're using Navigator.pop() at the Drawer(), the ".pop" function removes the Drawer and keeps the main page.
But at the time you use it with the ListTile(), which is part of the "main body" of the page, you just remove it.
Whatever collapses the main page when pressed, such a Drawer, Dialog or even a Keyboard, will be removed using Navigator.pop(), any other thing that is at the page which implements the "Navigator.pop()" will remove the page instead.
Navigator.of(context).pop();
this one is popping the screen in the flutter.
you can refer this doc as well https://api.flutter.dev/flutter/widgets/Navigator/pop.html
your home page doesn't have any stack behind it so when you have written Navigator.of(context).pop(); then it will pop the home page where there is not anything and it always shows the blank screen.
when you have tried Navigator.of(context).pop(); in the drawer then it has home page as a stack in the flutter which is the home page in your case and it will pop to the home page and show the blank page.

Flutter / flutter_webview_plugin => hide/show AppBar + BottomNavigationBar on Scroll down/up

I am using a WebviewScaffold. It works well, but now I want to hide the BottomNavigationBar and the AppBar on Scroll up. OnScroll down it should show the AppBar and BottomNavigationBar. Like it works in Chrome on iOS.
As I know I cant use a Sliver because
"Warning: The webview is not integrated in the widget tree, it is a native view on top of the flutter view. you won't be able to use snackbars, dialogs ..."
It would be Nice if somebody could help me.
Thanks in advance!
I found how to get ScrollParams.... But now I have to hide/show the AppBar and the BottomNavigationBar.
#override
void initState() {
// TODO: implement initState
super.initState();
_onScrollYChanged =
flutterWebViewPlugin.onScrollYChanged.listen((double x) {
if (mounted) {
print(_onScrollYChanged.toString());
setState(() {
if (_posY < x) {
_showBar = false;
print("DOWN");
} else {
_showBar = true;
print("UP");
}
_posY = x;
print("Scroll in Y Direction: $x");
});
}
});
}
My Build in my APP looks like this:
#override
Widget build(BuildContext context) {
return WebviewScaffold(
url: "https://www.domain.de",
appBar: AppBar(
toolbarOpacity: _showBar ? 1.0 : 0.0,
title: const Text('Widget WebView'),
leading: IconButton(
icon: Icon(Icons.apps),
onPressed: () {
flutterWebViewPlugin.goBack();
},
),
),
bottomNavigationBar: BottomAppBar(
color: Colors.blue,
child: Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () {
flutterWebViewPlugin.goBack();
},
),
],
),
),
withZoom: true,
withLocalStorage: true,
hidden: true,
headers: _HTMLheaders,
);
}
}

Resources