flutter PageView左右滑动切换视图

  • 网易云【玩转大前端】配套课程

  • EDU配套 教程

  • Flutter开发的点滴积累系列文章

  • 一行代代码置灰应用?对就是这么干

本文章描述分析 PageView的基本使用


1 PageView 的基本使用

  ///封装方法构建PageView组件
  PageView buildBodyFunction() {
    ///可实现左右页面滑动切换
    return PageView(
      //当页面选中后回调此方法
      //参数[index]是当前滑动到的页面角标索引 从0开始
      onPageChanged: (int index){
        print("当前的页面是 $index");
        ///滑动PageView时,对应切换选择高亮的标签
        setState(() {
          currentSelectIndex = index;
        });
      },
      //值为flase时 显示第一个页面 然后从左向右开始滑动
      //值为true时 显示最后一个页面 然后从右向左开始滑动
      reverse: false,
      //滑动到页面底部无回弹效果
      physics: BouncingScrollPhysics(),
      //横向滑动切换
      scrollDirection: Axis.horizontal,
      //页面控制器
      controller: pageController,
      //所有的子Widget
      children: pageList,
    );
  }
}

controller 与pageList


  ///当前显示标签页面的标识 
  int currentSelectIndex = 0;
  ///保存页面的List
  List<Widget> pageList=[];
  /// 初始化控制器
  PageController pageController;

  @override
  void initState() {
    super.initState();
    ///创建控制器的实例
    pageController = new PageController(
      ///用来配置PageView中默认显示的页面 从0开始
      initialPage: 0,
      ///为true是保持加载的每个页面的状态
      keepPage: true,
    );

    ///PageView设置滑动监听
    pageController.addListener(() {
      //PageView滑动的距离
      double offset = pageController.offset;
      print("pageView 滑动的距离 $offset");
    });

    ///保存标签页面
    pageList=[
      LeftPage(),
      RightPage(),
    ];
  }

使用 controller 来实现PageView的整屏切换

pageController.animateTo(MediaQuery.of(context).size.width*currentSelectIndex, duration: Duration(milliseconds: 200), curve: Curves.linear);

使用PageView滑动到顶部

pageController.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.linear);

2 案例实战 使用PageView实现引导页面

flutter PageView左右滑动切换视图_第1张图片

import 'dart:math';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_x/base/base_appbar_page.dart';

class LeftPageViewPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new LeftPageViewPageState();
  }
}

class LeftPageViewPageState extends BaseAppBarPageState<LeftPageViewPage> {
  @override
  String buildInitState() {
    buildBackBar("pageView", backIcon: Icons.arrow_back_ios);
    return null;
  }

  final _controller = new PageController();
  static const _kDuration = const Duration(milliseconds: 300);
  static const _kCurve = Curves.ease;
  final List<Widget> _pages = <Widget>[
    new ConstrainedBox(
      constraints: const BoxConstraints.expand(),
      child: new CachedNetworkImage(
        width: double.infinity,
        height: double.infinity,
        fit: BoxFit.fill,
        imageUrl:
            "http://b-ssl.duitang.com/uploads/item/201311/02/20131102150044_YGB5u.jpeg",
        placeholder: (context, url) => new SizedBox(
          width: 24.0,
          height: 24.0,
          child: new CircularProgressIndicator(
            strokeWidth: 2.0,
          ),
        ),
        errorWidget: (context, url, error) => new Icon(Icons.error),
      ),
    ),
    new ConstrainedBox(
      constraints: const BoxConstraints.expand(),
      child: new CachedNetworkImage(
        width: double.infinity,
        height: double.infinity,
        fit: BoxFit.fill,
        imageUrl:
            "http://b-ssl.duitang.com/uploads/item/201311/02/20131102150044_YGB5u.jpeg",
        placeholder: (context, url) => new SizedBox(
          width: 24.0,
          height: 24.0,
          child: new CircularProgressIndicator(
            strokeWidth: 2.0,
          ),
        ),
        errorWidget: (context, url, error) => new Icon(Icons.error),
      ),
    ),
    new ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: new Stack(
          //Stack即层叠布局控件,能够将子控件层叠排列
          //alignment:此参数决定如何去对齐没有定位(没有使用Positioned)或部分定位的子widget。所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。
          alignment: AlignmentDirectional.topStart,
          children: <Widget>[
            new CachedNetworkImage(
              width: double.infinity,
              height: double.infinity,
              fit: BoxFit.fill,
              imageUrl:  "http://b-ssl.duitang.com/uploads/item/201311/02/20131102150044_YGB5u.jpeg",
              placeholder: (context, url) => SizedBox(width: 24,height: 25,child: CircularProgressIndicator(strokeWidth: 2.0,),),
              errorWidget: (context, url, error) => new Icon(Icons.error),
            ),
            new Align(
              alignment: Alignment.bottomCenter,
              child: new Container(
                margin: EdgeInsets.only(bottom: 80.0),
                child: FlatButton(onPressed: (){}, child: Text("立即体验")) ,
              ),
            ),
          ],
        )),
  ];

  @override
  Widget buildWidget(BuildContext context) {
    // TODO: implement buildWidget
    return new Stack(
      children: <Widget>[
        //pageViw
        PageView.builder(
          physics: new AlwaysScrollableScrollPhysics(),
          controller: _controller,
          itemBuilder: (BuildContext context, int index) {
            return _pages[index];
          },
          //条目个数
          itemCount: _pages.length,
        ),
        //圆点指示器
        new Positioned(
          bottom: 0.0,
          left: 0.0,
          right: 0.0,
          child: new Container(
            color: Colors.white,
            padding: const EdgeInsets.all(20.0),
            child: new Center(
              child: new DotsIndicator(
                  controller: _controller,
                  itemCount: _pages.length,
                  onPageSelected: (int page) {
                    _controller.animateToPage(
                      page,
                      duration: _kDuration,
                      curve: _kCurve,
                    );
                  }),
            ),
          ),
        ),
      ],
    );
  }
}

class DotsIndicator extends AnimatedWidget {
  DotsIndicator({
    this.controller,
    this.itemCount,
    this.onPageSelected,
    this.color: Colors.red,
  }) : super(listenable: controller);

  /// The PageController that this DotsIndicator is representing.
  final PageController controller;

  /// The number of items managed by the PageController
  final int itemCount;

  /// Called when a dot is tapped
  final ValueChanged<int> onPageSelected;

  /// The color of the dots.
  ///
  /// Defaults to `Colors.white`.
  final Color color;

  // The base size of the dots
  static const double _kDotSize = 8.0;

  // The increase in the size of the selected dot
  static const double _kMaxZoom = 2.0;

  // The distance between the center of each dot
  static const double _kDotSpacing = 25.0;

  Widget _buildDot(int index) {
    double selectedness = Curves.easeOut.transform(
      max(
        0.0,
        1.0 - ((controller.page ?? controller.initialPage) - index).abs(),
      ),
    );
    double zoom = 1.0 + (_kMaxZoom - 1.0) * selectedness;
    return new Container(
      width: _kDotSpacing,
      child: new Center(
        child: new Material(
          color: color,
          type: MaterialType.circle,
          child: new Container(
            width: _kDotSize * zoom,
            height: _kDotSize * zoom,
            child: new InkWell(
              onTap: () => onPageSelected(index),
            ),
          ),
        ),
      ),
    );
  }

  Widget build(BuildContext context) {
    return new Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: new List<Widget>.generate(itemCount, _buildDot),
    );
  }
}

你可能感兴趣的:(flutter,flutter,从入门,到精通)