安卓开发Flutter圈子Flutter学习日记

Flutter笔记(四):PageView-Flutter中的V

2019-08-19  本文已影响7人  Yun丶Lei

PageView

使用PageView的三种方式

  PageView({
    Key key,
    this.scrollDirection = Axis.horizontal,  //方向
    this.reverse = false,  //是否和阅读方向一样的滚动,比如中文的阅读习惯系从左往右
    PageController controller,  //控制器
    this.physics,  //页面视图如何响应用户输入
    this.pageSnapping = true,  //使用自定义滚动时禁止页面捕捉
    this.onPageChanged,  //页面切换回调
    List<Widget> children = const <Widget>[],    //页面(组件)列表,页面个数等于长度
    this.dragStartBehavior = DragStartBehavior.start,  //拖拽行为
  })

后面两种方式去除重复数据

  PageView.builder({
    //...
    @required IndexedWidgetBuilder itemBuilder,  //创建item,根据回调index返回不同页面
    int itemCount,  //item数量
    //...
  })

第三种是自定义模式

  PageView.custom({
    //...
    @required this.childrenDelegate,  //自定义模式接受一个子页面委托对象
    //...
  })

这里主要以PageView.builder介绍一下PageView的使用

1、使用

//组件使用
PageView.builder(
  itemBuilder: (context, index) {
  return Center(
    child: _getPageByIndex(index),  //每个页面展示的组件
  );
  },
  itemCount: 4, //页面数量
  onPageChanged: _onPageChange, //页面切换
  controller: _pageController, //控制器
)
//返回每个页面子组件
StatefulWidget _getPageByIndex(int index) {
  switch (index) {
    case 0:
      return HomePage();
    case 1:
      return CategoryPage();
    case 2:
      return MeiZiPage();
    case 3:
      return AccountPage();
    default:
      return HomePage();
  }
}

2、关于controller

  PageController({
    this.initialPage = 0,    //初始化选择页面
    this.keepPage = true,    //是否保持已经渲染过得页面
    this.viewportFraction = 1.0,  //每个页面应占用的视口部分。 0~1之间
  })

在是使用PageView的时候会包含一个默认的控制器

var _pageController = PageController(initialPage: 0);

控制器跳转有4个已有的方法

  • animateToPage:带动画跳转
  • jumpToPage:直接改变当前页面无动画
  • nextPage:下一页
  • previousPage:上一页

来先看看jumpToPage的效果

_pageController.jumpToPage(_selectedIndex);
jumpToPage

再看看animateToPage的效果,ps:切换时间500ms,切换效果Curves.easeInOut

_pageController.animateToPage(_selectedIndex,
          duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
animateToPage

3、PageController的viewportFraction

每个页面应占用的视口部分。 0~1之间,比如设置为0.8可以得到以下效果,直接上图是最好的解释。再加点自动播放,循环播放之类的就是一个很nice的banner,但是这里只做demo演示,讲解以下这个属性,一般在flutter中banner不这样做,这样会有很多问题,比如拖拽时停止自动,pageView嵌套等问题。Flutter的概念里一切都是组件,banner组件我推荐轮子flutter_swiper

var _pageController = PageController(initialPage: 1, viewportFraction: 0.8);
viewportFraction: 0.8

4、配合BottomNavigationBar使用

关于BottomNavigationBar的使用可以参考我之前的
Flutter笔记(一):BottomNavigationBar常见问题
PageView和BottomNavigationBar联动的完整代码如下

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

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

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;
  var _pageController = PageController(initialPage: 0);

  void _incrementCounter() {
    setState(() {
      _selectedIndex++;
    });
  }

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    if (_pageController.hasClients) {
      _pageController.animateToPage(_selectedIndex,
          duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
//      _pageController.jumpToPage(_selectedIndex);
    }
  }

  void _onPageChange(int index) {
    print("_onPageChange");
    setState(() {
      _selectedIndex = index;
    });
  }

  StatefulWidget _getPageByIndex(int index) {
    switch (index) {
      case 0:
        return HomePage();
      case 1:
        return CategoryPage();
      case 2:
        return MeiZiPage();
      case 3:
        return AccountPage();
      default:
        return HomePage();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
          child: AppBar(
            backgroundColor: Colors.white,
            brightness: Brightness.light,
            title: Center(
              child: Text(
                "FlutterDemo",
              ),
            ),
          ),
          preferredSize: Size(double.infinity, 60)),
      body: PageView.builder(
        itemBuilder: (context, index) {
          return Center(
            child: _getPageByIndex(index),  //每个页面展示的组件
          );
        },
        itemCount: 4, //页面数量
        onPageChanged: _onPageChange, //页面切换
        controller: _pageController, //控制器
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
      bottomNavigationBar: new BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconhome), title: new Text("首页")),
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconcategory), title: new Text("分类")),
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconpic), title: new Text("妹子")),
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconaccount), title: new Text("我的")),
        ],
        selectedItemColor: Color(0xFF4CAF50),
        unselectedItemColor: Color(0xff666666),
        type: BottomNavigationBarType.fixed,
        showUnselectedLabels: true,
        onTap: _onItemTapped,
        currentIndex: _selectedIndex,
        selectedFontSize: 12.0,
      ),
    );
  }
}

疑问

如果要PageView嵌套使用,怎么处理滑动到边界时,父组件PageView不触发的问题?

上一篇下一篇

猜你喜欢

热点阅读