I am using flutter Webview plugin which works fine but today i face a issue while displaying a webpage which contains only a image with 100% width and height.
Therefore flutter Webview shows a blank page. When i change the height and width to a specific px for example 320px and 220px then only webview plugin shows the image otherwise with 100% the webpage goes blank.
You can try my plugin flutter_inappbrowser (EDIT: it has been renamed to flutter_inappwebview).
An example loading an html source directly in the InAppWebView widget with an img with width and height to 100%:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
#override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController webView;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialData: InAppWebViewInitialData(
data: """
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<img src="https://via.placeholder.com/300" alt="placeholder">
</body>
</html>
"""
),
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
),
),
),
]))
);
}
}
Related
The webview_flutter plugin is unable to play some YouTube embed videos that do work if played from within a web app. The videos display "Video unavailable". Playing YouTube videos inline in a Flutter app has been an issue for at least a year.
https://github.com/flutter/flutter/issues/13756
I have tried various Flutter plugins to play YouTube video inline but either they only support Android or don't work with YouTube.
I have tried using HTML string (YouTube iframe) directly inside WebView plugin but the video is unavailable. Loading HTML from a webserver allows for some videos to be played which otherwise didn't directly in the flutter app e.g. Some music videos display "Video unavailable. This video contains content from Vevo, who has blocked it from display on the website or application".
But if I launch the same video using the YouTube iframe API (see code) from a web application, it works without any errors i.e. the embed is not disabled but these videos don't play in Flutter app. I have also read similar issues with playing YouTube videos in Android where suggestion was to use a WebChromeClient, that is unavailable in Flutter.
Flutter app that displays a YouTube video inside WebView plugin.
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
// Use IP instead of localhost to access local webserver
const _youTubeUrl = 'http://localhost:8080';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YouTube Video',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'YouTube Video'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
WebViewController _controller;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
Expanded(
child: WebView(
initialUrl: '$_youTubeUrl/videos/IyFZznAk69U',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController controller) =>
_controller = controller,
),
),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.play_arrow),
onPressed: () async {
await _controller.evaluateJavascript('player.loadVideoById("d_m5csmrf7I")');
},
),
);
}
}
Node.js server side code that returns index.html via express routing
const path = require("path");
const express = require("express");
const server = express();
// Define route
api.get("/", (req, res) =>
res.sendFile(path.join(__dirname + "/index.html"))
);
const port = process.env.PORT || 8080;
server.listen(port, () => console.log(`Server listening on ${port}`));
process.on("exit", () => console.log("Server exited"));
index.html file that uses YouTube iframe API served to the Flutter app
<!DOCTYPE html>
<html>
<head>
<style>
#player {
position: relative;
padding-top: 56.25%;
min-width: 240px;
height: 0;
}
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
<script>
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player("yt", {
videoId: "IyFZznAk69U",
playerVars: {
autoplay: 1
}
});
}
</script>
<script src="https://www.youtube.com/iframe_api" async></script>
</head>
<body>
<div id="player">
<div id="yt"></div>
</div>
</body>
</html>
You can use my plugin flutter_inappwebview to play youtube videos inside a webview.
Full example with your youtube video id:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
#override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController webView;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://www.youtube.com/embed/IyFZznAk69U",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
),
),
),
]))
);
}
}
UPDATE: This plugin seems better (mentioned on the jira issue url) but not official from the Flutter team
https://github.com/hoanglm4/flutter_youtube_view
Is there any possibility to load complete website (including associated files) from local assets ? I tried it with flutter plugin webview_flutter and loaded index.html.
Future<String> loadLocal() async {
return await rootBundle.loadString('assets/mywebsite/index.html');
}
only html code is being rendered and associated javascripts are not working.
You can follow https://github.com/flutter/flutter/issues/27086
In the meantime you can implement a web server in Dart that serves files from assets and point the webview to that integrated web server.
https://medium.com/#segaud.kevin/facebook-oauth-login-flow-with-flutter-9adb717c9f2e is about how to do that in Dart.
I've been able to do this but it's working only in Android. I've used the InAppWebView library in the following way :
child: Container(
child: InAppWebView(
initialFile: "images/test.html",
initialHeaders: {},
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {},
onLoadStop: (InAppWebViewController controller, String url) {},
onConsoleMessage: (InAppWebViewController controller,
ConsoleMessage consoleMessage) {
print(consoleMessage.message);
},
),
),
The html file, including the related files have been added in the project assets.
You can try also 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 load a complete website from assets, you need to declare the corresponding files in the pubspec.yaml file:
...
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/index.html
- assets/page-1.html
- assets/page-2.html
- assets/js/
- assets/css/
- assets/images/
...
Then, you can load your index.html file using initialFile parameter of the InAppWebView widget:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
#override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController webView;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
onConsoleMessage: (InAppWebViewController controller, ConsoleMessage consoleMessage) {
print(consoleMessage.message);
},
),
),
),
]))
);
}
}
In your index.html you will have something like that:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- this is a css file inside the assets folder -->
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- this is a javascript file inside the assets folder -->
<script src="js/main.js"></script>
</body>
</html>
I am new to Flutter and I wanted to have splash screen in my app. I used initState() and the navigator. But it didn't work. The app opens the splashscreen appears but after that it does not navigate to the next screen.
My main.dart
import 'package:flutter/material.dart';
import 'package:bmi/HomePage.dart';
import 'dart:async';
main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return SplashScreen();
}
}
class SplashScreen extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return SplashScreenState();
}
}
class SplashScreenState extends State<SplashScreen>{
#override
void initState() {
super.initState();
Future.delayed(
Duration(
seconds: 4
),
(){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
)
);
}
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.red,
body: Text(
'Welcome to BMI Calculator',
style: new TextStyle(
fontSize: 15.0,
color: Colors.white,
fontWeight: FontWeight.bold
),
),
),
);
}
}
And my HomePage.dart
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text(
'BMI Calculator',
style: new TextStyle(
color: Colors.white
),
),
),
),
);
}
}
How can I resolve this?
Since I am new to flutter I dont know whether this is the right way to implement splashScreen if there are any other easier ways can you please suggest that also.
Thank you in advance.
Code Corrected:
MaterialApp should be the parent(root) of all Widgets.
import 'package:flutter/material.dart';
import 'package:bmi/HomePage.dart';
import 'dart:async';
main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: SplashScreen()); // define it once at root level.
}
}
class SplashScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return SplashScreenState();
}
}
class SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 4), () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.red,
body: Text(
'Welcome to BMI Calculator',
style: new TextStyle(
fontSize: 15.0, color: Colors.white, fontWeight: FontWeight.bold),
),
);
}
}
class HomePage extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text(
'BMI Calculator',
style: new TextStyle(
color: Colors.white
),
),
),
);
}
}
The splash screen implementation is provided by default.
You just need to change the code in respective platforms like below
For Android:
Go to android directory in your flutter project and find the res folder where you will have launch_background.xml under drawables , just replace your own splash image as below.
`
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="center"
android:src="#drawable/hotel_logo_new" />
</item>
</layer-list>
For iOS
- just change the LaunchImage under ImageAssets.
You should use pushReplacement instead of push when you exit the splash screen to prevent it from showing again when you press the back button.
here's the anmol.majhail code with the correct behavior.
import 'package:flutter/material.dart';
import 'package:bmi/HomePage.dart';
import 'dart:async';
main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: SplashScreen()); // define it once at root level.
}
}
class SplashScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return SplashScreenState();
}
}
class SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 4), () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.red,
body: Text(
'Welcome to BMI Calculator',
style: new TextStyle(
fontSize: 15.0, color: Colors.white, fontWeight: FontWeight.bold),
),
);
}
}
class HomePage extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text(
'BMI Calculator',
style: new TextStyle(
color: Colors.white
),
),
),
);
}
}
To use this package : add the dependency to your pubspec.yaml file.
dependencies:
flutter:
sdk: flutter
splashscreen:
How to use
import 'package:flutter/material.dart';
import 'package:splashscreen/splashscreen.dart';
main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SplashScreen(
seconds: 10,
imageBackground: AssetImage('assets/images/a.jpg'),
navigateAfterSeconds: HomeScreen(),
),
); // define it once at root level.
}
}
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text(
'Home',
style: new TextStyle(color: Colors.white),
),
),
);
}
}
Simple solution which i use in every app.
Use Timer class in build method code snippet
class SplashScreen extends StatefulWidget {
#override
Splash createState() => Splash();
}
class Splash extends State<SplashScreen> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
Timer(
Duration(seconds: 3),
() =>
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => LandingScreen())));
var assetsImage = new AssetImage(
'images/new_logo.png'); //<- Creates an object that fetches an image.
var image = new Image(
image: assetsImage,
height:300); //<- Creates a widget that displays an image.
return MaterialApp(
home: Scaffold(
/* appBar: AppBar(
title: Text("MyApp"),
backgroundColor:
Colors.blue, //<- background color to combine with the picture :-)
),*/
body: Container(
decoration: new BoxDecoration(color: Colors.white),
child: new Center(
child: image,
),
), //<- place where the image appears
),
);
}
}
Is it possible to display an iframe in Dart?
Below is the code that I am using
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final wordPair = WordPair.random();
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Text(wordPair.asPascalCase), // With this highlighted text.
),
),
);
}
}
I am not sure how to add an iframe into this. Below is the snippet that is given in the documentation
factory IFrameElement() => JS(
'returns:IFrameElement;creates:IFrameElement;new:true',
'#.createElement(#)',
document,
"iframe");
I agree that using webview_flutter plugin shows HTML in Flutter. But, this plugin is currently supported in mobile but not yet for web. Here is an example of how you implement this on mobile:
Sample code using webview_flutter plugin:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
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: 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> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: WebView(
initialUrl: 'https://flutter.dev/',
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
javascriptMode: JavascriptMode.unrestricted,
),
);
}
}
Actual Output:
And regarding your question how to implement IFrameElement. There is actually an existing blog where it provides all the steps to understand this. But as mentioned, this is still in beta.
After I followed all the necessary steps, I've ended up in this example:
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:html';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: IframeDemo(),
),
),
);
}
}
class IframeDemo extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyWidget();
}
}
class MyWidget extends State<IframeDemo> {
String _url;
IFrameElement _iframeElement;
#override
initState() {
super.initState();
_url = 'https://flutter.dev/';
_iframeElement = IFrameElement()
..src = _url
..id = 'iframe'
..style.border = 'none';
//ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'iframeElement',
(int viewId) => _iframeElement,
);
}
#override
Widget build(BuildContext context) {
print('url is $_url');
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
),
SizedBox(
height: 600,
width: 600,
child: HtmlElementView(
viewType: 'iframeElement',
),
),
],
);
}
}
Sample Output:
By implementation of FlutterWebviewPlugin, I want to show a particular website in a widget but without header and footer.
is this possible in Flutter?
I guess there is a function in FlutterWebviewPlugin class .evalJavascript('some code') but don't know how to use this function. can I add javascript code to this?
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
String url = "https://flutter.io/";
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Webview Example',
theme: ThemeData.dark(),
routes: {
"/": (_) => Home(),
"/webview": (_) => WebviewScaffold(
url: url,
withJavascript: true,
withLocalStorage: true,
withZoom: true,
)
},
);
}
}
class Home extends StatefulWidget {
#override
HomeState createState() => HomeState();
}
class HomeState extends State<Home> {
final webView = FlutterWebviewPlugin();
TextEditingController controller = TextEditingController(text: url);
#override
void initState() {
super.initState();
webView.close();
controller.addListener(() {
url = controller.text;
});
}
#override
void dispose() {
webView.dispose();
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("WebView"),
),
body: Center(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10.0),
child: TextField(
controller: controller,
),
),
RaisedButton(
child: Text("Open Webview"),
onPressed: () {
Navigator.of(context).pushNamed("/webview");
},
)
],
),
)
);
}
}
I suggest using Flutter's official WebView plugin: webview_flutter
The plugin also has a method that can run Javascript using WebViewController.evaluateJavascript(String). This method is recommended to be run after WebView.onPageFinished callback.
Your WebView widget should look like this.
WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_webViewController = webViewController;
_controller.complete(webViewController);
},
onProgress: (int progress) {
print("WebView is loading (progress : $progress%)");
},
onPageStarted: (String url) {
print('Page started loading: $url');
},
onPageFinished: (String url) {
print('Page finished loading: $url');
// Removes header and footer from page
_webViewController
.evaluateJavascript("javascript:(function() { " +
"var head = document.getElementsByTagName('header')[0];" +
"head.parentNode.removeChild(head);" +
"var footer = document.getElementsByTagName('footer')[0];" +
"footer.parentNode.removeChild(footer);" +
"})()")
.then((value) => debugPrint('Page finished loading Javascript'))
.catchError((onError) => debugPrint('$onError'));
},
);
Here's a complete sample that you can try.
import 'dart:async';
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(
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> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
WebViewController _webViewController;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Builder(builder: (BuildContext context) {
return WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_webViewController = webViewController;
_controller.complete(webViewController);
},
onProgress: (int progress) {
print("WebView is loading (progress : $progress%)");
},
javascriptChannels: <JavascriptChannel>{
_toasterJavascriptChannel(context),
},
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
print('allowing navigation to $request');
return NavigationDecision.navigate;
},
onPageStarted: (String url) {
print('Page started loading: $url');
},
onPageFinished: (String url) {
print('Page finished loading: $url');
_webViewController
.evaluateJavascript("javascript:(function() { " +
"var head = document.getElementsByTagName('header')[0];" +
"head.parentNode.removeChild(head);" +
"var footer = document.getElementsByTagName('footer')[0];" +
"footer.parentNode.removeChild(footer);" +
"})()")
.then((value) => debugPrint('Page finished loading Javascript'))
.catchError((onError) => debugPrint('$onError'));
},
gestureNavigationEnabled: true,
);
}),
);
}
JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
return JavascriptChannel(
name: 'Toaster',
onMessageReceived: (JavascriptMessage message) {
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(message.message)),
);
});
}
}
How the app looks running
_webViewController.runJavascript(
"document.getElementsByTagName('header')[0].style.display='none'");
_webViewController.runJavascript(
"document.getElementsByTagName('footer')[0].style.display='none'");
You can use the flutter_inappwebview plugin (I'm the author) and inject an UserScript at UserScriptInjectionTime.AT_DOCUMENT_START to hide or remove HTML elements when the web page loads (check JavaScript - User Scripts official docs for User Scripts details).
As I have already answered here for a similar issue, here is a code example using the current latest version 6 (6.0.0-beta.18) with URL https://getmobie.de/impressum that removes the header and footer HTML elements:
import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb &&
kDebugMode &&
defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("InAppWebView test"),
),
body: Column(children: <Widget>[
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest:
URLRequest(url: WebUri("https://getmobie.de/impressum")),
initialUserScripts: UnmodifiableListView([
UserScript(source: """
window.addEventListener('DOMContentLoaded', function(event) {
var header = document.querySelector('.elementor-location-header'); // use here the correct CSS selector for your use case
if (header != null) {
header.remove(); // remove the HTML element. Instead, to simply hide the HTML element, use header.style.display = 'none';
}
var footer = document.querySelector('.elementor-location-footer'); // use here the correct CSS selector for your use case
if (footer != null) {
footer.remove(); // remove the HTML element. Instead, to simply hide the HTML element, use footer.style.display = 'none';
}
});
""", injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START)
]),
onWebViewCreated: (controller) {
webViewController = controller;
},
),
),
]));
}
}
For your use case, use the right CSS selector inside the user script js source to correctly get and remove the header and footer HTML elements from your web page!