构造方法以及参数:
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的资料请关注代码网其它相关文章!
发表评论