Flutter开发Widgets 之 PageView使用示例

2022-10-22,,,

构造方法以及参数:

pageview可用于widget的整屏滑动切换,如当代常用的短视频app中的上下滑动切换的功能,也可用于横向页面的切换,如app第一次安装时的引导页面,也可用于开发轮播图功能.

  pageview({
    key? key,
    this.scrolldirection = axis.horizontal, // 设置滚动方向 垂直 / 水平 
    this.reverse = false,	// 反向滚动 
    pagecontroller? controller,	// 滚动控制类 
    this.physics,	// 滚动逻辑 , 不滚动 / 滚动 / 滚动到边缘是否反弹 
    this.pagesnapping = true,	// 如果设置 false , 则无法进行页面手势捕捉 
    this.onpagechanged, 	// 页面切换时回调该函数 
    list<widget> children = const <widget>[],
    this.dragstartbehavior = dragstartbehavior.start,
    this.allowimplicitscrolling = false,
    this.restorationid,
    this.clipbehavior = clip.hardedge,
  }) : assert(allowimplicitscrolling != null),
       assert(clipbehavior != null),
       controller = controller ?? _defaultpagecontroller,
       childrendelegate = sliverchildlistdelegate(children),
       super(key: key);

具体参数说明:

scrolldirection主要是滚动的方向即horizontal(水平)和vertical(垂直)两个,默认是horizontal的

reverse这个就是规定了children(子节点)的排序是否是倒序,默认false。这个参数在listview也有,一般在做im工具聊天内容用listview展示时需要倒序展示的。

controller可以传入一个pagecontroller的实例进去,可以更好的控制pageview的各种动作,可以设置:

  • 初始页面(initialpage)、
  • 是否保存pageview状态(keeppage)
  • 每一个pageview子节点的内容占改视图的比例(viewportfraction)
  • 直接调转到指定的pageview的子节点的方法(jumptopage
  • 动画(平滑移动)到指定的pageview的子节点的方法(animatetopage)
  • 到下一个pageview的子节点的方法(nextpage)
  • 到上一个pageview的子节点的方法(previouspage)
    从以上可以看出基本是普通轮播图组件的api

physics就是设置滑动效果:

  • neverscrollablephysics表示设置的不可滚动
  • bouncingscrollphysics表示滚动到底了会有弹回的效果,就是ios的默认交互
  • clampingscrollphysics表示滚动到底了就给一个效果,就是android的默认交互
  • fixedextentscrollphysics就是ios经典选择时间组件uidatepicker那种交互。

pagesnapping就是设置是不是整页滚动,默认是true.

dragstartbehavior这个属性是设置认定开始拖动行为的方式,可以选择的是down和start两个,默认是start. down是第一个手指按下认定拖动开始,start是手指拖动才算开始。

allowimplicitscrolling这个属性一般提供给视障人士使用的,默认是fasle

基本用法

pageview控件可以实现一个“图片轮播”的效果,pageview不仅可以水平滑动也可以垂直滑动,简单用法如下:

pageview(
      children: [
        container(color: colors.red,),
        container(color: colors.black,),
        container(color: colors.yellow,),
      ],
    );

pageview滚动方向默认是水平,可以设置其为垂直方向:

pageview(
    scrolldirection: axis.vertical,
    ...
)

pageview配合pagecontroller可以实现非常酷炫的效果,控制每一个page不占满,

container(
      height:200 ,
      child: pageview(
        scrolldirection: axis.horizontal,
        controller: pagecontroller(viewportfraction: 0.9),
        children: [
          container(color: colors.red,),
          container(color: colors.black,),
          container(color: colors.yellow,),
        ],
      ),
    );

pagecontroller中属性initialpage表示当前加载第几页,默认第一页。

onpagechanged属性是页面发生变化时的回调,用法如下:

无限滚动

pageview滚动到最后时希望滚动到第一个页面,这样看起来pageview是无限滚动的:

list<widget> pagelist = [pageview1(), pageview2(), pageview3()];
pageview.builder(
    itemcount: 10000,
    itembuilder: (context, index) {
        return pagelist[index % (pagelist.length)];
    },
)

实现指示器

指示器显示总数和当前位置,通过onpagechanged确定当前页数并更新指示器。

 int _currentpageindex = 0;
  list<widget> pagelist = [ container(color: colors.red,),
    container(color: colors.black,),
    container(color: colors.yellow,),];
 _buildpageview(){
    return center(
      child: container(
        height: 230,
        child: stack(
          children: [
            pageview.builder(itembuilder: (context,index){
              var val = pagelist[index%(pagelist.length)];
              print(val);
              return _buildpageviewitem('${val}');
            }),
            positioned(
                bottom: 20,
                left: 0,
                right: 0,
                child: container(
                  child: row(
                    mainaxisalignment: mainaxisalignment.center,
                    children: list.generate(pagelist.length, (i){
                      return container(
                        margin: edgeinsets.symmetric(horizontal: 5),
                        width: 10,
                        height: 10,
                        decoration: boxdecoration(
                          shape: boxshape.circle,
                          color: _currentpageindex==i?colors.blue:colors.grey
                        ),
                      );
                    }).tolist(),
                  ),
                )
            )
          ],
        ),
      ),
    );
  }
  _buildpageviewitem(string txt,{color color=colors.red}){
    return container(
      color: color,
      alignment: alignment.center,
      child: text(txt,style: textstyle(color: colors.white,fontsize: 25),),
    );
  }

切换动画

如此常见的切换效果显然不能体验我们独特的个性,我们需要更炫酷的方式,看下面的效果:

在滑出的时候当前页面逐渐缩小并居中,通过给pagecontroller添加监听获取当前滑动的进度:

_pagecontroller.addlistener(() {
      setstate(() {
        _currpagevalue = _pagecontroller.page;
      });
    });

全部代码:

/**
 * @author wywinstonwy
 * @date 2022/10/05 9:50 上午
 * @description:
 */
import 'package:demo202112/utils/common_appbar.dart';
import 'package:flutter/material.dart';
class wypageview1 extends statefulwidget {
  const wypageview1({key? key}) : super(key: key);
  @override
  _wypageviewstate createstate() => _wypageviewstate();
}
class _wypageviewstate extends state<wypageview1> {
  int _currentpageindex = 0;
  var imglist = [
    'https://ss1.bdstatic.com/70cfvxsh_q1ynxgkpowk1hf6hhy/it/u=2877516247,37083492&fm=26&gp=0.jpg',
    'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582796218195&di=04ce93c4ac826e19067e71f916cec5d8&imgtype=0&src=http%3a%2f%2fhbimg.b0.upaiyun.com%2f344fda8b47808261c946c81645bff489c008326f15140-koinr3_fw658'
  ];
  late pagecontroller _pagecontroller;
  var _currpagevalue=0;
  //缩放系数
  double _scalefactor = .8;
  //view page height
  double _height = 230.0;
  @override
  void initstate() {
    // todo: implement initstate
    super.initstate();
    _pagecontroller=pagecontroller(viewportfraction: 0.9);
    _pagecontroller.addlistener(() {
      setstate(() {
        _currpagevalue = _pagecontroller.page;
      });
    });
  }
  @override
  void dispose() {
    // todo: implement dispose
    super.dispose();
    _pagecontroller.dispose();
  }
  @override
  widget build(buildcontext context) {
    return scaffold(
      appbar: getappbar('pageview'),
      body: container(
          height: _height,
          child: pageview.builder(
            itembuilder: (context, index) => _buildpageitem(index),
            itemcount: 10,
            controller: _pagecontroller,
          )),
    );
  }
  _buildpageitem(int index) {
    matrix4 matrix4 = matrix4.identity();
    if (index == _currpagevalue.floor()) {
      //当前的item
      double currscale = (1 - (_currpagevalue - index) * (1 - _scalefactor)).todouble();
      var currtrans = _height * (1 - currscale) / 2;
      matrix4 = matrix4.diagonal3values(1.0, currscale, 1.0)
        ..settranslationraw(0.0, currtrans, 0.0);
    } else if (index == _currpagevalue.floor() + 1) {
      //右边的item
      var currscale =
          _scalefactor + (_currpagevalue - index + 1) * (1 - _scalefactor);
      var currtrans = _height * (1 - currscale) / 2;
      matrix4 = matrix4.diagonal3values(1.0, currscale, 1.0)
        ..settranslationraw(0.0, currtrans, 0.0);
    } else if (index == _currpagevalue.floor() - 1) {
      //左边
      var currscale = (1 - (_currpagevalue - index) * (1 - _scalefactor)).todouble();
      var currtrans = _height * (1 - currscale) / 2;
      matrix4 = matrix4.diagonal3values(1.0, currscale, 1.0)
        ..settranslationraw(0.0, currtrans, 0.0);
    } else {
      //其他,不在屏幕显示的item
      matrix4 = matrix4.diagonal3values(1.0, _scalefactor, 1.0)
        ..settranslationraw(0.0, _height * (1 - _scalefactor) / 2, 0.0);
    }
    return transform(
      transform: matrix4,
      child: padding(
        padding: edgeinsets.symmetric(horizontal: 10),
        child: container(
          decoration: boxdecoration(
            borderradius: borderradius.circular(12),
            image: decorationimage(
                image: networkimage(imglist[index % 2]), fit: boxfit.fill),
          ),
        ),
      ),
    );
  }
}

gitdemo地址:gitee.com/wywinstonwy…

总结:

相比熟悉android和ios开发的同学都会比较熟悉viewpager,可以在界面上滑动多个界面view的切换。在flutter中同样有这样的组建那就是pageview,相比于viewpager它有着更加强大的功能,毕竟flutter中widget是一等公民,在实际开发中也是比较实用的组件,可以提升开发效率。

以上就是flutter开发widgets 之 pageview使用示例的详细内容,更多关于flutter开发widgets pageview的资料请关注其它相关文章!

《Flutter开发Widgets 之 PageView使用示例.doc》

下载本文的Word格式文档,以方便收藏与打印。