本篇用一个PageView的实例来加深印象,而且在以后的专栏里,咱们会深化这个示例,作成一个支持上下左右无限滑动的图片Banner,而且教你如何把他作成Dart library而且开放给其余人使用。 bash
在实现PageView指示器以前,我们须要先实现一个PageView。在Flutter中实现一个PageView很简单。less
class BannerGalleryWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return BannerGalleryWidgetState();
}
}
class BannerGalleryWidgetState extends State<BannerGalleryWidget> {
final PageController controller = PageController(initialPage: 200);
@override
Widget build(BuildContext context) {
return SizedBox(
height: 250.0,
child: Container(
color: Colors.grey,
child: PageView.builder(
controller: controller,
itemBuilder: (context, index) {
return new Center(
child: new Text('页面 ${index}'),
);
},
),
));
}
}
复制代码
以上代码会得出这样一个界面。稍微解释一下代码:ide
/// 指定一个控制器,用来控制PageView的滑动,以及初始位置在第200页
/// 主要为了实现“无限循环”
final PageController controller = PageController(initialPage: 200);
/// 一个固定大小的容器,这里指定了他的高为250
SizedBox(height: 250.0)
/// 一个容器,用来设定背景颜色为灰色
Container(color: Colors.grey)
/// 主角PageView,文字居中显示当前的索引。
PageView.builder(
controller: controller,
itemBuilder: (context, index) {
return new Center(
child: new Text('页面 ${index}'),
);},),
复制代码
有了无限滑动的PageView以后,我们再来关联一个指示器:布局
class Indicator extends StatelessWidget {
Indicator({
this.controller,
this.itemCount: 0,
}) : assert(controller != null);
/// PageView的控制器
final PageController controller;
/// 指示器的个数
final int itemCount;
/// 普通的颜色
final Color normalColor = Colors.blue;
/// 选中的颜色
final Color selectedColor = Colors.red;
/// 点的大小
final double size = 8.0;
/// 点的间距
final double spacing = 4.0;
/// 点的Widget
Widget _buildIndicator(
int index, int pageCount, double dotSize, double spacing) {
// 是不是当前页面被选中
bool isCurrentPageSelected = index ==
(controller.page != null ? controller.page.round() % pageCount : 0);
return new Container(
height: size,
width: size + (2 * spacing),
child: new Center(
child: new Material(
color: isCurrentPageSelected ? selectedColor : normalColor,
type: MaterialType.circle,
child: new Container(
width: dotSize,
height: dotSize,
),
),
),
);
}
@override
Widget build(BuildContext context) {
return new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: new List<Widget>.generate(itemCount, (int index) {
return _buildIndicator(index, itemCount, size, spacing);
}),
);
}
}
复制代码
这段代码比较简单,在build()方法里面构建了一个横向的List。 List的Item是一个固定大小的圆点,选中是一种颜色,没有选中是另外一种颜色。ui
class BannerGalleryWidgetState2 extends State<BannerGalleryWidget2> {
final PageController controller = PageController(initialPage: 200);
void _pageChanged(int index) {
setState(() {});
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SizedBox(
height: 150.0,
child: Container(
color: Colors.grey,
child: PageView.builder(
onPageChanged: _pageChanged,
controller: controller,
itemBuilder: (context, index) {
return new Center(
child: new Text('页面 ${index}'),
);
},
),
)),
Indicator(
controller: controller,
itemCount: 5,
),
],
);
}
}
复制代码
把布局容器改一下,用一个列包裹PageView和Indicator,给PageView加一个onPageChanged,检查当页面修改的时候setState()刷新UI就行了。this
四.总结 至此,无限滑动的PageView指示器已经完成了,虽然看起来和专栏一开始的示例图片有点小小的差异,可是至少需求实现了。可是如今这个指示器还比较傻,好比选中以后才会变色,并且不会放大显示。在以后的专栏里我教你们如何完善这个指示器以及提供整个工程的完整代码,敬请期待。spa