如何正确的在Flutter中添加webview
Posted 前端码农小王
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何正确的在Flutter中添加webview相关的知识,希望对你有一定的参考价值。
前言
为什么要在flutter中引入webview?这不是废话么,当然是为了加载一个网页,这不是移动端最基本的需求么,哈哈!说的真不错,接下来我要是告诉你我的用法,你可能要大吃一惊。我的用处很简单,那就是在webview中再加载一个flutter编译成web的项目。有没有吓到你。别怕,我这么做的原因很简单,就是为了热更新。可能在flutter中实现热更新的方法有很多,但我敢说我这么做就是最好的热更新方式。当我内容发生变更是时候,我不需要继续去审核,只需要在服务器中,更新内容,我的热更新就实现了!是不是听着很动心,那就赶紧学起来吧。
安装
在Flutter应用开发中,由于官方并没有提供类似Webview的网页加载组件,所以如果项目中涉及网页加载就需要使用第三方插件库。网上第三方插件库很多,我不推荐,自行百度搜索比较,用法基本雷同,webview_flutter是Flutter官方开发和维护的网页加载插件库。所以今天我讲讲它的使用方法
1.在pubspec.yaml文件中添加依赖脚本(并运行隐式flutter pub get)
dependencies:flutter:sdk: fluttercupertino_icons: ^1.0.2webview_flutter: ^3.0.4
2.使用
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:webview_flutter/webview_flutter.dart';
class WebviewApp extends StatefulWidget const WebviewApp(Key? key) : super(key: key);@overrideState<WebviewApp> createState() => _WebviewAppState();
class _WebviewAppState extends State<WebviewApp> @overridevoid initState() super.initState();if (Platform.isandroid) WebView.platform = AndroidWebView();@overrideWidget build(BuildContext context) return const WebView(initialUrl: 'https://www.baidu.com',javascriptMode: JavascriptMode.unrestricted,);
好了,这样我们就成功引入了webview,并在webview中加载了百度首页。你高兴的去运行项目,结果却傻眼了,终端一片红,好了,我来说说爆红的解决方案。
运行项目遇到的问题
One or more plugins require a higher Android SDK version.
- 解决方案:找到 项目根目录\\android\\app\\build.gradle,修改如下配置:
android compileSdkVersion 32
Error: uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library
- 解决方案:找到 项目根目录\\android\\app\\build.gradle,修改如下配置:
defaultConfig applicationId "com.example.flutter_jsbridge_js"minSdkVersion 20targetSdkVersion 30versionCode flutterVersionCode.toInteger()versionName flutterVersionName
net:ERR_CLEARTEXT_NOT_PERMITTED
这时候运行项目已经已经不会报错了,但是webview却显示一串神奇代码:net:ERR_CLEARTEXT_NOT_PERMITTED,这是因为从 Android 9(API 级别 28)开始,明文支持默认处于禁用状态。
- 解决方案:
1.创建文件:/xml/network_security_config.xml
目录路径:“项目根目录/android/app/main/res”
<?xml version="1.0" encoding="utf-8"?>
<network-security-config><domain-config cleartextTrafficPermitted="true"><domain includeSubdomains="true">api.example.com(to be adjusted)</domain></domain-config>
</network-security-config>
2.对AndroidManifest.xml文件做修改:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...><uses-permission android:name="android.permission.INTERNET" /><application...android:networkSecurityConfig="@xml/network_security_config"...>...</application>
</manifest>
这时候再去运行项目,就可以正常运行了,画面显示正常,如果你还需要遇到其他问题,可以留言一起解决。
最后
为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。
有需要的小伙伴,可以点击下方卡片领取,无偿分享
如何从 webview flutter 中删除 Header 并在底部导航图标中添加下划线
【中文标题】如何从 webview flutter 中删除 Header 并在底部导航图标中添加下划线【英文标题】:How to remove Header from webview flutter and add underline in bottom navigation icon 【发布时间】:2021-09-01 00:30:22 【问题描述】:我无法从 web 视图中删除标题。有没有办法删除 webview 网站的标题并将应用程序标题应用到 web 视图,这样网站标题就被删除了,我们的应用栏作为标题显示在应用程序上。
我想在底部导航栏下的 svg 图标上添加黄色下划线,但我无法添加,请帮帮我。 Home page of my app
import 'dart:async';
import 'package:url_launcher/url_launcher.dart';
import 'dart:io';
/* import 'package:titled_navigation_bar/titled_navigation_bar.dart' ;*/
import 'package:flutter_svg/flutter_svg.dart';
/* import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; */
import 'package:webview_flutter/webview_flutter.dart';
/* import 'package:md2_tab_indicator/md2_tab_indicator.dart'; */
/*import 'package:flutter_inappwebview/flutter_inappwebview.dart'; */
main()
runApp(MyApp());
// ignore: use_key_in_widget_constructors
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(home: SplashScreen()); // define it once at root level.
// ignore: use_key_in_widget_constructors
class SplashScreen extends StatefulWidget
@override
State<StatefulWidget> createState()
return SplashScreenState();
class SplashScreenState extends State<SplashScreen>
@override
void initState()
super.initState();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
Timer(
// ignore: prefer_const_constructors
Duration(seconds: 1),
() => Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomeScreen())));
@override
Widget build(BuildContext context)
return Scaffold(
backgroundColor: Colors.black,
body: Center(child: Image.asset('assets/splash.jpeg')),
);
// ignore: use_key_in_widget_constructors
class HomeScreen extends StatefulWidget
@override
_MyAppState createState() => _MyAppState();
class _MyAppState extends State<HomeScreen>
final Completer<WebViewController> _controller =
Completer<WebViewController>();
num _stackToView = 1;
int _selectedTabIndex = 0;
// ignore: prefer_final_fields
List _pages = [
// ignore: prefer_const_constructors
Text("Home"),
// ignore: prefer_const_constructors
Text("Wishlist"),
// ignore: prefer_const_constructors
Text("Search"),
// ignore: prefer_const_constructors
Text("Bookings"),
// ignore: prefer_const_constructors
Text("Menu"),
Text("call"),
];
_changeIndex(int index)
setState(()
_selectedTabIndex = index;
);
void _handleLoad(String value)
setState(()
_stackToView = 0;
);
@override
Widget build(BuildContext context)
final textTheme = Theme.of(context).textTheme;
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
appBar: AppBar(
/* automaticallyImplyLeading: false, */
leading: Padding(
padding: EdgeInsets.all(10.0),
child: SvgPicture.asset("assets/svg/VW-logo.svg"),
/* leadingWidth: 35, */
),
actions: [
IconButton(
icon: SvgPicture.asset("assets/svg/new.svg", color: Colors.black),
onPressed: () ,
),
IconButton(
icon: SvgPicture.asset("assets/svg/Page-1.svg"),
onPressed: ()
_launchURL();
,
),
],
backgroundColor: Colors.white),
body:
/* const WebView(
initialUrl: 'https://www.google.com/',
javascriptMode: JavascriptMode.unrestricted,
), */
/* Center(child: _pages[_selectedTabIndex]), */
IndexedStack(
index: _selectedTabIndex,
children: [
Column(
children: <Widget>[
Expanded(
child: WebView(
initialUrl: "https://www.veenaworld.com/",
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: _handleLoad,
onWebViewCreated: (WebViewController webViewController)
_controller.complete(webViewController);
,
)),
],
),
Container(
child: Center(child: _pages[_selectedTabIndex]),
),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedTabIndex,
onTap: _changeIndex,
type: BottomNavigationBarType.fixed,
/* backgroundColor: Colors.blue.shade900, */
selectedLabelStyle: textTheme.caption,
unselectedLabelStyle: textTheme.caption,
/* Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 1.0, color: Colors.black),
),
),
), */
selectedItemColor: Colors.black,
unselectedItemColor: Colors.black.withOpacity(.60),
items: [
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/svg/home-alt2.svg",
color: Colors.black),
title: Text("Home")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/svg/favourite.svg",
color: Colors.black),
title: Text("Wishlist")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/svg/search.svg",
color: Colors.black),
title: Text("Search")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/svg/bag.svg", color: Colors.black),
title: Text("Bookings")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/svg/hamburger.svg",
color: Colors.black),
title: Text("Menu"))
],
),
);
_launchURL() async
const url = 'https://www.google.com/';
if (await canLaunch(url))
await launch(url);
else
throw 'Could not launch $url';
【问题讨论】:
也许你可以挂上onPageFinished
并执行一些类似let appBar = document.getElementById("appBar"); appBar.parentNode.removeChild(appBar);
的js,有两个问题......好吧,这只是第一个......
除了使用flutter web view requests之外,没有javascript实现会导致繁重的调试sme其他解决方案
我认为无法使用 Flutter 对 webview 内容进行任何更改,只能执行一些 js.... 一个选项可能是您发送 yourpage.com?dontshowappbar=true
并将其隐藏webapp 或更改 webview 中的 user-agent
并在 webapp 或服务器端进行处理
【参考方案1】:
对于操纵 WebView,我认为没有办法做到这一点,也许您可以使用像堆栈这样的技巧来隐藏 WebView appbar,如下所示:
@override
Widget build(BuildContext context)
final textTheme = Theme.of(context).textTheme;
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
// appBar: AppBar(
// /* automaticallyImplyLeading: false, */
// leading: Padding(
// padding: EdgeInsets.all(10.0),
// child: SvgPicture.asset("assets/images/Helmet.svg"),
//
// /* leadingWidth: 35, */
// ),
// actions: [
// IconButton(
// icon: SvgPicture.asset("assets/images/Helmet.svg",
// color: Colors.black),
// onPressed: () ,
// ),
// ],
// backgroundColor: Colors.white),
body: Stack(
children: [
IndexedStack(
index: _selectedTabIndex,
children: [
Column(
children: <Widget>[
Expanded(
child: WebView(
initialUrl: "https://www.veenaworld.com/",
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: _handleLoad,
onWebViewCreated: (WebViewController webViewController)
_controller.complete(webViewController);
,
)),
],
),
Container(
child: Center(child: _pages[_selectedTabIndex]),
),
],
),
AppBar(
/* automaticallyImplyLeading: false, */
leading: Padding(
padding: EdgeInsets.all(10.0),
child: SvgPicture.asset("assets/images/Helmet.svg"),
/* leadingWidth: 35, */
),
actions: [
IconButton(
icon: SvgPicture.asset("assets/images/Helmet.svg",
color: Colors.black),
onPressed: () ,
),
],
backgroundColor: Colors.white,
),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedTabIndex,
onTap: _changeIndex,
type: BottomNavigationBarType.fixed,
/* backgroundColor: Colors.blue.shade900, */
selectedLabelStyle: textTheme.caption,
unselectedLabelStyle: textTheme.caption,
/* Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 1.0, color: Colors.black),
),
),
), */
selectedItemColor: Colors.black,
unselectedItemColor: Colors.black.withOpacity(.60),
items: [
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/images/Helmet.svg",
color: Colors.black),
title: Text("Home")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/images/Helmet.svg",
color: Colors.black),
title: Text("Wishlist")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/images/Helmet.svg",
color: Colors.black),
title: Text("Search")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/images/Helmet.svg",
color: Colors.black),
title: Text("Bookings")),
BottomNavigationBarItem(
icon: SvgPicture.asset("assets/images/Helmet.svg",
color: Colors.black),
title: Text("Menu"))
],
),
);
【讨论】:
以上是关于如何正确的在Flutter中添加webview的主要内容,如果未能解决你的问题,请参考以下文章
如何正确地将库模块依赖项添加到 Flutter Plugin 的 Android 文件夹? [关闭]