- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有 4 个底部导航栏,每个都有一个 webview。
但是当点击一个底部导航栏并在网页 View 页面中选择一个部分时,我无法通过按钮返回设备返回 webview 中的上一页。
我想通过后退按钮设备回到 webview。
现在是按下后退按钮退出应用程序的时候。
但我使用 double_back_to_close_app.dart 退出应用程序。
家庭类:
import 'package:webview_flutter/webview_flutter.dart';
import 'package:fancy_bar/fancy_bar.dart';
import 'placeholder_widget.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _currentIndex = 0;
final List<Widget> _children = [
MyPlaceholderWidget('https://googel.com'),
MyPlaceholderWidget('https://googel.com'),
MyPlaceholderWidget('https://googel.com'),
MyPlaceholderWidget('https://googel.com')
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(40.0),
child: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.grey[200],
elevation: 0.0,
)
),
body: DoubleBackToCloseApp(
child: _children[_currentIndex],
snackBar: const SnackBar(
content: Text(
'برای خروج دو بار کلیک کنید',
style: TextStyle(fontFamily: "Shabnam"),
textDirection: TextDirection.rtl,
textAlign: TextAlign.center,
),
),
),
bottomNavigationBar: FancyBottomBar(
onItemSelected: onTabTapped,
selectedIndex: _currentIndex, // this will be set when a new tab is tapped
items: [
FancyItem(
textColor: Colors.green,
title: 'حساب',
icon: Icon(
LineIcons.user,
size: 29,
),
),
FancyItem(
textColor: Colors.green,
title: 'وبلاگ',
icon: Icon(
LineIcons.file_text,
size: 27,
),
),
FancyItem(
textColor: Colors.green,
title: 'سبد خرید',
icon: Icon(
LineIcons.shopping_cart,
size: 31,
),
),
FancyItem(
textColor: Colors.green,
title: 'صفحه اصلی',
icon: Icon(
LineIcons.home,
size: 28,
),
),
],
),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
}
WebViewController controller;
class MyPlaceholderWidget extends StatelessWidget {
var url = 'https://www.mayehtaj.ir' ;
final key = UniqueKey();
MyPlaceholderWidget(String url){
this.url = url ;
}
@override
Widget build(BuildContext context) {
return WebView(
key: key,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: url,
onWebViewCreated: (WebViewController webViewController){
controller = webViewController;
});
}
}
最佳答案
您可以在下面复制粘贴运行完整代码
您可以换行 Scaffold
与 WillPopScope
当用户点击 device back button
,可以执行WebView Controller goback
代码 fragment onwillpop
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _exitApp(context),
child: Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView example'),
// This drop down menu demonstrates that Flutter widgets can be shown over the web view.
actions: <Widget>[
NavigationControls(_controller.future),
SampleMenu(_controller.future),
],
),
WebViewController controllerGlobal;
Future<bool> _exitApp(BuildContext context) async {
if (await controllerGlobal.canGoBack()) {
print("onwill goback");
controllerGlobal.goBack();
} else {
Scaffold.of(context).showSnackBar(
const SnackBar(content: Text("No back history item")),
);
return Future.value(false);
}
}
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(MaterialApp(home: WebViewExample()));
const String kNavigationExamplePage = '''
<!DOCTYPE html><html>
<head><title>Navigation Delegate Example</title></head>
<body>
<p>
The navigation delegate is set to block navigation to the youtube website.
</p>
<ul>
<ul><a href="https://www.youtube.com/">https://www.youtube.com/</a></ul>
<ul><a href="https://www.google.com/">https://www.google.com/</a></ul>
<ul><a href="https://www.google.com/">https://nodejs.org/en</a></ul>
</ul>
</body>
</html>
''';
class WebViewExample extends StatefulWidget {
@override
_WebViewExampleState createState() => _WebViewExampleState();
}
WebViewController controllerGlobal;
Future<bool> _exitApp(BuildContext context) async {
if (await controllerGlobal.canGoBack()) {
print("onwill goback");
controllerGlobal.goBack();
} else {
Scaffold.of(context).showSnackBar(
const SnackBar(content: Text("No back history item")),
);
return Future.value(false);
}
}
class _WebViewExampleState extends State<WebViewExample> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _exitApp(context),
child: Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView example'),
// This drop down menu demonstrates that Flutter widgets can be shown over the web view.
actions: <Widget>[
NavigationControls(_controller.future),
SampleMenu(_controller.future),
],
),
// We're using a Builder here so we have a context that is below the Scaffold
// to allow calling Scaffold.of(context) so we can show a snackbar.
body: Builder(builder: (BuildContext context) {
return WebView(
initialUrl: 'https://flutter.dev',
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;
}
if (request.url.startsWith('https://flutter.dev/docs')) {
print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
print('allowing navigation to $request');
return NavigationDecision.navigate;
},
onPageFinished: (String url) {
print('Page finished loading: $url');
},
);
}),
floatingActionButton: favoriteButton(),
),
);
}
JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
return JavascriptChannel(
name: 'Toaster',
onMessageReceived: (JavascriptMessage message) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(message.message)),
);
});
}
Widget favoriteButton() {
return FutureBuilder<WebViewController>(
future: _controller.future,
builder: (BuildContext context,
AsyncSnapshot<WebViewController> controller) {
if (controller.hasData) {
return FloatingActionButton(
onPressed: () async {
final String url = await controller.data.currentUrl();
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Favorited $url')),
);
},
child: const Icon(Icons.favorite),
);
}
return Container();
});
}
}
enum MenuOptions {
showUserAgent,
listCookies,
clearCookies,
addToCache,
listCache,
clearCache,
navigationDelegate,
}
class SampleMenu extends StatelessWidget {
SampleMenu(this.controller);
final Future<WebViewController> controller;
final CookieManager cookieManager = CookieManager();
@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: controller,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
return PopupMenuButton<MenuOptions>(
onSelected: (MenuOptions value) {
switch (value) {
case MenuOptions.showUserAgent:
_onShowUserAgent(controller.data, context);
break;
case MenuOptions.listCookies:
_onListCookies(controller.data, context);
break;
case MenuOptions.clearCookies:
_onClearCookies(context);
break;
case MenuOptions.addToCache:
_onAddToCache(controller.data, context);
break;
case MenuOptions.listCache:
_onListCache(controller.data, context);
break;
case MenuOptions.clearCache:
_onClearCache(controller.data, context);
break;
case MenuOptions.navigationDelegate:
_onNavigationDelegateExample(controller.data, context);
break;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
PopupMenuItem<MenuOptions>(
value: MenuOptions.showUserAgent,
child: const Text('Show user agent'),
enabled: controller.hasData,
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.listCookies,
child: Text('List cookies'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.clearCookies,
child: Text('Clear cookies'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.addToCache,
child: Text('Add to cache'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.listCache,
child: Text('List cache'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.clearCache,
child: Text('Clear cache'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.navigationDelegate,
child: Text('Navigation Delegate example'),
),
],
);
},
);
}
void _onShowUserAgent(
WebViewController controller, BuildContext context) async {
// Send a message with the user agent string to the Toaster JavaScript channel we registered
// with the WebView.
controller.evaluateJavascript(
'Toaster.postMessage("User Agent: " + navigator.userAgent);');
}
void _onListCookies(
WebViewController controller, BuildContext context) async {
final String cookies =
await controller.evaluateJavascript('document.cookie');
Scaffold.of(context).showSnackBar(SnackBar(
content: Column(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Cookies:'),
_getCookieList(cookies),
],
),
));
}
void _onAddToCache(WebViewController controller, BuildContext context) async {
await controller.evaluateJavascript(
'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";');
Scaffold.of(context).showSnackBar(const SnackBar(
content: Text('Added a test entry to cache.'),
));
}
void _onListCache(WebViewController controller, BuildContext context) async {
await controller.evaluateJavascript('caches.keys()'
'.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))'
'.then((caches) => Toaster.postMessage(caches))');
}
void _onClearCache(WebViewController controller, BuildContext context) async {
await controller.clearCache();
Scaffold.of(context).showSnackBar(const SnackBar(
content: Text("Cache cleared."),
));
}
void _onClearCookies(BuildContext context) async {
final bool hadCookies = await cookieManager.clearCookies();
String message = 'There were cookies. Now, they are gone!';
if (!hadCookies) {
message = 'There are no cookies.';
}
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(message),
));
}
void _onNavigationDelegateExample(
WebViewController controller, BuildContext context) async {
final String contentBase64 =
base64Encode(const Utf8Encoder().convert(kNavigationExamplePage));
controller.loadUrl('data:text/html;base64,$contentBase64');
}
Widget _getCookieList(String cookies) {
if (cookies == null || cookies == '""') {
return Container();
}
final List<String> cookieList = cookies.split(';');
final Iterable<Text> cookieWidgets =
cookieList.map((String cookie) => Text(cookie));
return Column(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: cookieWidgets.toList(),
);
}
}
class NavigationControls extends StatelessWidget {
const NavigationControls(this._webViewControllerFuture)
: assert(_webViewControllerFuture != null);
final Future<WebViewController> _webViewControllerFuture;
@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
final bool webViewReady =
snapshot.connectionState == ConnectionState.done;
final WebViewController controller = snapshot.data;
controllerGlobal = controller;
return Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: !webViewReady
? null
: () async {
if (await controller.canGoBack()) {
controller.goBack();
} else {
Scaffold.of(context).showSnackBar(
const SnackBar(content: Text("No back history item")),
);
return;
}
},
),
IconButton(
icon: const Icon(Icons.arrow_forward_ios),
onPressed: !webViewReady
? null
: () async {
if (await controller.canGoForward()) {
controller.goForward();
} else {
Scaffold.of(context).showSnackBar(
const SnackBar(
content: Text("No forward history item")),
);
return;
}
},
),
IconButton(
icon: const Icon(Icons.replay),
onPressed: !webViewReady
? null
: () {
controller.reload();
},
),
],
);
},
);
}
}
关于android - 通过后退按钮设备在 webview 中回退,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60176497/
我最近在/ drawable中添加了一些.gifs,以便可以将它们与按钮一起使用。这个工作正常(没有错误)。现在,当我重建/运行我的应用程序时,出现以下错误: Error: Gradle: Execu
Android 中有返回内部存储数据路径的方法吗? 我有 2 部 Android 智能手机(Samsung s2 和 s7 edge),我在其中安装了一个应用程序。我想使用位于这条路径中的 sqlit
这个问题在这里已经有了答案: What's the difference between "?android:" and "@android:" in an android layout xml f
我只想知道 android 开发手机、android 普通手机和 android root 手机之间的实际区别。 我们不能从实体店或除 android marketplace 以外的其他地方购买开发手
自Gradle更新以来,我正在努力使这个项目达到标准。这是一个团队项目,它使用的是android-apt插件。我已经进行了必要的语法更改(编译->实现和apt->注释处理器),但是编译器仍在告诉我存在
我是android和kotlin的新手,所以请原谅要解决的一个非常简单的问题! 我已经使用导航体系结构组件创建了一个基本应用程序,使用了底部的导航栏和三个导航选项。每个导航选项都指向一个专用片段,该片
我目前正在使用 Facebook official SDK for Android . 我现在正在使用高级示例应用程序,但我不知道如何让它获取应用程序墙/流/状态而不是登录的用户。 这可能吗?在那种情
我在下载文件时遇到问题, 我可以在模拟器中下载文件,但无法在手机上使用。我已经定义了上网和写入 SD 卡的权限。 我在服务器上有一个 doc 文件,如果用户单击下载。它下载文件。这在模拟器中工作正常但
这个问题在这里已经有了答案: What is the difference between gravity and layout_gravity in Android? (22 个答案) 关闭 9
任何人都可以告诉我什么是 android 缓存和应用程序缓存,因为当我们谈论缓存清理应用程序时,它的作用是,缓存清理概念是清理应用程序缓存还是像内存管理一样主存储、RAM、缓存是不同的并且据我所知,缓
假设应用程序 Foo 和 Eggs 在同一台 Android 设备上。任一应用程序都可以获取设备上所有应用程序的列表。一个应用程序是否有可能知道另一个应用程序是否已经运行以及运行了多长时间? 最佳答案
我有点困惑,我只看到了从 android 到 pc 或者从 android 到 pc 的例子。我需要制作一个从两部手机 (android) 连接的 android 应用程序进行视频聊天。我在想,我知道
用于使用 Android 以编程方式锁定屏幕。我从 Stackoverflow 之前关于此的问题中得到了一些好主意,并且我做得很好,但是当我运行该代码时,没有异常和错误。而且,屏幕没有锁定。请在这段代
文档说: android:layout_alignParentStart If true, makes the start edge of this view match the start edge
我不知道这两个属性和高度之间的区别。 以一个TextView为例,如果我将它的layout_width设置为wrap_content,并将它的width设置为50 dip,会发生什么情况? 最佳答案
这两个属性有什么关系?如果我有 android:noHistory="true",那么有 android:finishOnTaskLaunch="true" 有什么意义吗? 最佳答案 假设您的应用中有
我是新手,正在尝试理解以下 XML 代码: 查看 developer.android.com 上的文档,它说“starStyle”是 R.attr 中的常量, public static final
在下面的代码中,为什么当我设置时单选按钮的外观会发生变化 android:layout_width="fill_parent" 和 android:width="fill_parent" 我说的是
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
假设我有一个函数 fun myFunction(name:String, email:String){},当我调用这个函数时 myFunction('Ali', 'ali@test.com ') 如何
我是一名优秀的程序员,十分优秀!