Flutter Pageview 在方向改变时丢失索引
Flutter Pageview loses index on orientation change
最近也有类似的问题,但是已经在 GitHub 上解决并关闭了。
因为我是新手,所以我可能会在这里遗漏一些东西。
方向更改后,页面索引恢复为零,但选定的 BottomNavigationBarItem 保持原样。
这里显示页面“ONE”,但在旋转设备之前选择了选项卡“FOUR”
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Pageview Orientation Bug',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _page = 0;
PageController _controller = PageController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: OrientationBuilder(
builder: (context,orientation) {
return orientation == Orientation.portrait
? Column(
children: [
Expanded(child: Container(color: Colors.grey)),
Expanded(
child: PageView(
controller: _controller,
children: [Text("ONE"), Text("TWO"),Text("THREE"), Text("FOUR"),],
),
),
],
)
: Row(
children: [
Expanded(child: Container(color: Colors.grey)),
Expanded(
child: PageView(
controller: _controller,
children: [Text("ONE"), Text("TWO"),Text("THREE"), Text("FOUR"),],
),
),
],
);
}
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _page,
onTap: (page) {
setState(() {
_page = page;
});
_controller.jumpToPage(page);
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.directions_bike),
label: "ONE",
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_boat_outlined),
label: "TWO",
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_car),
label: "THREE",
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_run),
label: "FOUR",
),
],
),
);
}
}
将 final Key _key = GlobalKey();
添加到 HomeState
并将 key
传递给两个 PageView
构造函数。这将告诉 Flutter 它是相同的 PageView
并且确实需要移动,而不是在方向改变时被替换。
在编写代码时,每次都会创建一个新的 PageView
元素而不维护状态,因此在构建时使用 PageController
的 initialValue
。
不相关的建议
PageView
是可滚动的,并且在编写代码时,如果用户滚动,它不会更新 BottomNavigationBar
。根据您所追求的用户体验,以下是几种方法。
PageView(
// use never scrollable physics if you only want the user to change pages via the nav bar
physics: NeverScrollableScrollPhysics(),
// use onPageChanged to sync scroll and nav bar
onPageChanged: (page) {
// remove this line from nav bar onTap
setState(() => _page = page);
},
key: _key,
controller: _controller,
children: [
Text("ONE"),
Text("TWO"),
Text("THREE"),
Text("FOUR"),
],
),
最近也有类似的问题,但是已经在 GitHub 上解决并关闭了。
因为我是新手,所以我可能会在这里遗漏一些东西。
方向更改后,页面索引恢复为零,但选定的 BottomNavigationBarItem 保持原样。
这里显示页面“ONE”,但在旋转设备之前选择了选项卡“FOUR”
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Pageview Orientation Bug',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _page = 0;
PageController _controller = PageController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: OrientationBuilder(
builder: (context,orientation) {
return orientation == Orientation.portrait
? Column(
children: [
Expanded(child: Container(color: Colors.grey)),
Expanded(
child: PageView(
controller: _controller,
children: [Text("ONE"), Text("TWO"),Text("THREE"), Text("FOUR"),],
),
),
],
)
: Row(
children: [
Expanded(child: Container(color: Colors.grey)),
Expanded(
child: PageView(
controller: _controller,
children: [Text("ONE"), Text("TWO"),Text("THREE"), Text("FOUR"),],
),
),
],
);
}
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _page,
onTap: (page) {
setState(() {
_page = page;
});
_controller.jumpToPage(page);
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.directions_bike),
label: "ONE",
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_boat_outlined),
label: "TWO",
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_car),
label: "THREE",
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_run),
label: "FOUR",
),
],
),
);
}
}
将 final Key _key = GlobalKey();
添加到 HomeState
并将 key
传递给两个 PageView
构造函数。这将告诉 Flutter 它是相同的 PageView
并且确实需要移动,而不是在方向改变时被替换。
在编写代码时,每次都会创建一个新的 PageView
元素而不维护状态,因此在构建时使用 PageController
的 initialValue
。
不相关的建议
PageView
是可滚动的,并且在编写代码时,如果用户滚动,它不会更新 BottomNavigationBar
。根据您所追求的用户体验,以下是几种方法。
PageView(
// use never scrollable physics if you only want the user to change pages via the nav bar
physics: NeverScrollableScrollPhysics(),
// use onPageChanged to sync scroll and nav bar
onPageChanged: (page) {
// remove this line from nav bar onTap
setState(() => _page = page);
},
key: _key,
controller: _controller,
children: [
Text("ONE"),
Text("TWO"),
Text("THREE"),
Text("FOUR"),
],
),