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 元素而不维护状态,因此在构建时使用 PageControllerinitialValue

不相关的建议

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"),
  ],
),