Flutter 学习笔记(九)Flutter中的pageView

3,428 阅读1分钟

1. physics的参数

flutter中PageView 默认是可以左右滑动的,如果想禁止滑动修改physics的参数为NeverScrollableScrollPhysics(),即可

 PageView(
          physics: const NeverScrollableScrollPhysics(),
          children: <Widget>[
            Page1(),
            Page2(),
            Page3(),
            Page4(),
            Page5(),
          ],
          controller: pageController,
          onPageChanged: onPageChanged,
 ),

在 Flutter 中,ScrollPhysics 的作用是确定可滚动控件的物理特性, 常见的有以下几个:

ScrollPhysics释义
BouncingScrollPhysics允许滚动出边界,超过边界时会有回弹效果,会响应滚动事件
ClampingScrollPhysics不允许滚动出边界,会响应滚动事件
AlwaysScrollableScrollPhysics一直响应滚动事件
NeverScrollableScrollPhysics禁止滚动,不响应滚动事件
FixedExtentScrollPhysicsListWheelScrollView滚轮使用时,item都会停止在中间位置,不会停在分割线
PageScrollPhysicsPageView滚轮使用时,item都会停止在一页,不会停止在分割线位置
RangeMaintainingScrollPhysics当内容突然改变尺寸时,试图将滚动位置保持在范围内的滚动物理

滚动条案例:

// main.dart
import 'package:flutter/material.dart';
import 'pages/home.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

// home.dart

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';


class HomePage extends StatefulWidget {
  HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool showFab = false;
  ScrollController? _scrollController;
  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
  }

  void dispose() {
    _scrollController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Firebase Notifications")),
        body: NotificationListener<UserScrollNotification>(
          onNotification: (notification) {
            setState(() {
              if (notification.direction == ScrollDirection.forward) {
                showFab = false;
              } else if (notification.direction == ScrollDirection.reverse) {
                showFab = true;
              }
            });

            return true;
          },
          child: ListView.builder(
              itemCount: 200,
              controller: _scrollController,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(title: Text('Item $index'));
              }),
        ),
        floatingActionButton: showFab
            ? FloatingActionButton(
                child: Icon(Icons.arrow_downward_rounded),
                onPressed: () {
                  _scrollController
                      ?.jumpTo(_scrollController!.position.maxScrollExtent);
                },
              )
            : null);
  }
}

2. controller

参考链接:juejin.cn/post/697397…

页面滑动案例

// main.dart
import 'package:flutter/material.dart';
import 'pages/demo/demo1.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PageViewPage(),
    );
  }
}

// demo1.dart
import 'package:flutter/material.dart';

class PageViewPage extends StatefulWidget {
  PageViewPage({Key? key}) : super(key: key);

  @override
  _PageViewPageState createState() => _PageViewPageState();
}

class _PageViewPageState extends State<PageViewPage> {
  // 当前子项索引
  int currentIndex = 0;
  // 子项集
  late List<Widget> children;
  // 控制器
  late PageController _controller;

  @override
  void initState() {
    super.initState();
    // 初始化控制器
    _controller = PageController();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('PageView - ZeroFlutter'),
        ),
        // 这里改为 PageView
        body: PageView(
          // 设置控制器
          controller: _controller,
          // 设置子项集
          children: <Widget>[
            PageDetails(title: '首页'),
            PageDetails(title: '消息'),
            PageDetails(title: '我的'),
          ],
          // 添加页面滑动改变后,去改变索引变量刷新页面来更新底部导航
          onPageChanged: (value) {
            currentIndex = value;
            setState(() {});
          },
        ),
        bottomNavigationBar: BottomNavigationBar(
          // 当前页面索引
          currentIndex: currentIndex,
          // 导航子项集
          items: [
            // 导航子项
            BottomNavigationBarItem(
              // 图标
              icon: Icon(Icons.home),
              // 文字内容
              label: '首页',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.message_rounded),
              label: '消息',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.people),
              label: '我的',
            ),
          ],
          onTap: (value) {
            // 点击事件,用于改变当前索引,然后刷新
            setState(() {
              currentIndex = value;
            });
            // 通过控制器实现跳转页面
            _controller.jumpToPage(currentIndex);
          },
        ));
  }
}

class PageDetails extends StatefulWidget {
  PageDetails({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _PageDetailsState createState() => _PageDetailsState();
}
//- 这里混入了 AutomaticKeepAliveClientMixin
class _PageDetailsState extends State<PageDetails>
    with AutomaticKeepAliveClientMixin {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    super.build(context);
    // 这里的打印可以记录一下,后面会用到
    print('PageDetails build title:${widget.title}');
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          setState(() {
            count += 1;
          });
        },
        child: Center(
          child: Text('${widget.title} count:$count'),
        ),
      ),
    );
  }

  // 设置 true 期望保持页面状态
  @override
  bool get wantKeepAlive => true;
}