Flutter开发者

PageView

2020-05-10

PageView

相比熟悉Android和IOS开发的同学都会比较熟悉ViewPager,可以在界面上滑动多个界面View的切换。在Flutter中同样有这样的组建那就是PageView,相比于ViewPager它有着更加强大的功能,毕竟Flutter中Widget是一等公民,下面我们就来看看如何使用它。

首先我们还是先看一下PageView的构造方法

1
2
3
4
5
6
7
8
9
10
11
PageView({
Key key,
this.scrollDirection = Axis.horizontal, //方向,默认为横向
this.reverse = false, //是否反转方向
PageController controller, //控制器
this.physics, //页面视图如何响应用户输入
this.pageSnapping = true, //使用自定义滚动时禁止页面捕捉
this.onPageChanged, //页面切换回调
List<Widget> children = const <Widget>[], //页面(组件)列表,页面个数等于长度
this.dragStartBehavior = DragStartBehavior.start, //拖拽行为
})

PageView主要三种创建的方式,上面的构造方法就是第一种,首先我们来看下如何使用它。

首先我们构造一个PageItem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class PageItem extends StatelessWidget {
final String title;
final Color color;

PageItem(this.title, this.color);

@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
color: color,
child: Center(
child: Text(title),
),
);
}
}

然后直接在PageView中使用它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Scaffold(
appBar: AppBar(
title: Text("PageView0Title"),
),
body: Container(
child: PageView(
children: [
PageItem("Page1", Colors.blueAccent),
PageItem("Page2", Colors.tealAccent),
PageItem("Page3", Colors.greenAccent),
PageItem("Page4", Colors.amberAccent),
],
),
),

这里我们仅仅声明了children属性,来看下效果

现在我们试着来改变scrollDirection: Axis.vertical,再看下效果

当然的如果设置reverse: true你就会得到相反的数据

同样的我们可以声明 来控制PageView,比如设置默认offset,动态跳转到指定页面等。

1
2
3
4
5
6
7
8
PageController controller;
@override
void initState() {
super.initState();
controller =
PageController(initialPage: 0, keepPage: true, viewportFraction: 2.0);

}

我们也可以使用onPageChanged来监听页面变化,然后我们结合BottomNavigationBar来实现滑动与底部按钮点击同步切换页面的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: HomePage(),
));
}

class HomePage extends StatefulWidget {
@override
_MyState createState() => _MyState();
}

class _MyState extends State<HomePage> {
PageController controller;
int _currentSelect = 0;
void onSelect(int index) {
setState(() {
_currentSelect = index;
controller.animateToPage(index,duration: Duration(milliseconds: 400),curve: Curves.easeInOut);
});
}

@override
void initState() {
controller =
PageController(initialPage: 0, keepPage: true, viewportFraction: 2.0);
super.initState();
}

@override
void dispose() {
super.dispose();
controller.dispose();
}

@override
Widget build(BuildContext context) {
const _defaultColor = Colors.blue;
const _selectColor = Colors.greenAccent;
return Scaffold(
appBar: AppBar(
title: Text("PageViewTitle"),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Text(
'Home',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.wb_cloudy,
),
title: Text(
'Cloudy',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.wb_sunny,
),
title: Text(
'Sunny',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.person,
),
title: Text(
'Mine',
))
],
unselectedItemColor: _defaultColor,
selectedItemColor: _selectColor,
currentIndex: _currentSelect,
onTap: (index) => onSelect(index),
type: BottomNavigationBarType.fixed,
),
body: Container(
alignment: Alignment.center,
child: PageView(
children: [
PageItem("Page1", Colors.blueAccent),
PageItem("Page2", Colors.tealAccent),
PageItem("Page3", Colors.greenAccent),
PageItem("Page4", Colors.amberAccent),
],
controller: controller,
onPageChanged: (value) {
onSelect(value);
print(value);
},
),
),
);
}
}

class PageItem extends StatelessWidget {
final String title;
final Color color;

PageItem(this.title, this.color);

@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
color: color,
child: Center(
child: Text(title),
),
);
}
}

下面我们来看下PageView.builder()方法来创建PageView,其实更加的简单,主要用于大量数据动态的创建工作会相对简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: HomePage(),
));
}

class HomePage extends StatefulWidget {
@override
_MyState createState() => _MyState();
}

class _MyState extends State<HomePage> {
List<PageItem> item = List();

@override
void initState() {
item.add(PageItem("home", Colors.redAccent));
item.add(PageItem("Cloudy", Colors.blueAccent));
item.add(PageItem("Sunny", Colors.yellowAccent));
item.add(PageItem("Mine", Colors.greenAccent));
super.initState();
}

@override
void dispose() {
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("PageView1Title"),
),
body: Container(
child: PageView.builder(
itemBuilder: (BuildContext context, int index) {
return item[index];
},
itemCount: item.length,
),
),
);
}
}

class PageItem extends StatelessWidget {
final String title;
final Color color;

PageItem(this.title, this.color);

@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
color: color,
child: Center(
child: Text(title),
),
);
}
}

当然效果并不会有什么差别的,这里就不贴图了。

PageView.custom()的创建方式就是使用一个自定义的委托类来创建Item,以控制用于估计实际上不可见的子项大小的算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Container(
child: PageView.custom(
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return KeepAlive(
keepAlive: true,
child: item[index],
);
},
findChildIndexCallback: (Key key) {
final ValueKey valueKey = key;
final PageItem data = valueKey.value;
return item.indexOf(data);
},
childCount: item.length,
),
),
)
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

打赏请备注姓名或者昵称,方便我后期统计哦

关注公众号,及时查阅最新文章