持续创作,加快生长!这是我参加「日新方案 · 10 月更文应战」的第8天,点击查看活动概况
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是一等公民,在实践开发中也是比较实用的组件,能够提升开发效率。