我使用bottomNavigationBar
在几页之间切换。其中两个页面使用WebView
来显示本地html文件。
我发现,当我在这些页面之间切换时,带有纯颤动小部件的页面可以完美加载。但是HTML页面只会在切换时显示最初加载的页面。
例如,如果我有两个指向Page1和Page2的导航器按钮,则在运行时,如果我先轻按Page1按钮,然后轻按Page2按钮,则WebView仍将显示Page1而不是Page2。这是错误的。
这是我使用的HTML页面代码
class LocalLoader {
Future<String> loadLocal(String filename) async {
return await rootBundle.loadString('assets/doc/$filename');
}
}
class HtmlPage extends StatelessWidget {
final String htmlFile;
HtmlPage({
@required this.htmlFile
});
@override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder<String>(
future: LocalLoader().loadLocal(htmlFile),
builder: (context, snapshot) {
if (snapshot.hasData) {
return WebView(
initialUrl: Uri.dataFromString(snapshot.data,
mimeType: 'text/html',
// CAUTION
// - required for non-ascii chars
encoding: Encoding.getByName("UTF-8")
).toString(),
javascriptMode: JavascriptMode.unrestricted,
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
} else {
print('undefined behaviour');
}
return CircularProgressIndicator();
},
),);
}
}
然后用我的bottomNavigationBar
处理点击事件:
class MyFlutterView extends StatefulWidget {
@override
_MyFlutterViewState createState() => _MyFlutterViewState();
}
class _MyFlutterViewState extends State<MyFlutterView> {
final Keys keys = Keys();
int _iSelectedDrawerItem = 3; // self
int _iSelectedNavItem = 0;
static List<Widget> _widgetOptions = <Widget>[
MyFlutterPlaceholder(title: 'Index 0: MyFlutter'),
MyPage(htmlFile: 'page1.html'),
MyPage(htmlFile: 'page2.html'),
];
void _onItemTapped(int index) {
setState(() {
_iSelectedNavItem = index;
});
}
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
final appBar = AppBar(
backgroundColor: WidgetColors.menubar,
title: Text('MyFlutter'),
);
return Scaffold(
appBar: appBar,
endDrawer: NavDrawer(
keys: keys,
iSelectedDrawerItem: _iSelectedDrawerItem,
),
body: Container(
decoration: BoxDecoration(
gradient: WidgetColors.canvas,
),
child: _widgetOptions.elementAt(_iSelectedNavItem),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex : _iSelectedNavItem,
type: BottomNavigationBarType.fixed,
backgroundColor: WidgetColors.menubar,
fixedColor: WidgetColors.myColor,
// selectedItemColor: WidgetColors.myColor,
unselectedItemColor: Colors.white,
selectedIconTheme: IconThemeData(color: WidgetColors.myColor),
// unselectedIconTheme: IconThemeData(color: Colors.white),
items: [
BottomNavigationBarItem(
label: 'MyFlutter',
icon: Icon(Icons.build)
),
BottomNavigationBarItem(
label: 'Page1-HTML',
icon: Icon(Icons.help,),
),
BottomNavigationBarItem(
label: 'Page2-HTML',
icon: Icon(Icons.info_outline_rounded),
),
],
onTap: _onItemTapped),
);
}
}
我也尝试过StatefulWidgets
,但问题仍然存在。
我目前唯一的解决方法是从HtmlPage
类派生我拥有的每个页面,就像这样:
class Page1 extends HtmlPage {
Page1() : super(htmlFile: 'page1.html');
}
class Page2 extends HtmlPage {
Page2() : super(htmlFile: 'page2.html');
}
此后,HTML页面将按预期切换并加载。
该如何解决?我应该更明确地加载HTML文件吗?我以为setState
会自动为我处理加载,这当然适用于纯flutter小部件页面(上面代码中的MyFlutterPlaceholder
类)。
此外,我确保每次通过导航栏切换页面时都调用URL加载。
答案 0 :(得分:1)
您可以在下面复制粘贴运行完整代码
我用下面的完整代码模拟这种情况
步骤1:使用AutomaticKeepAliveClientMixin
class _WebViewKeepAlive extends State<WebViewKeepAlive>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
步骤2:请勿在{{1}}属性future
中直接放置函数,请按以下方式使用
future: LocalLoader().loadLocal(htmlFile),
第3步:在这种情况下,我使用Future<String> _future;
@override
void initState() {
_future = _getUrl(widget.url);
super.initState();
}
return FutureBuilder(
future: _future,
工作演示
完整代码
PageView