PageView
使用PageView的三種方式
PageView({
Key key,
this.scrollDirection = Axis.horizontal, //方向
this.reverse = false, //是否和閱讀方向一樣的滾動(dòng),比如中文的閱讀習(xí)慣系從左往右
PageController controller, //控制器
this.physics, //頁面視圖如何響應(yīng)用戶輸入
this.pageSnapping = true, //使用自定義滾動(dòng)時(shí)禁止頁面捕捉
this.onPageChanged, //頁面切換回調(diào)
List<Widget> children = const <Widget>[], //頁面(組件)列表,頁面?zhèn)€數(shù)等于長度
this.dragStartBehavior = DragStartBehavior.start, //拖拽行為
})
后面兩種方式去除重復(fù)數(shù)據(jù)
PageView.builder({
//...
@required IndexedWidgetBuilder itemBuilder, //創(chuàng)建item,根據(jù)回調(diào)index返回不同頁面
int itemCount, //item數(shù)量
//...
})
第三種是自定義模式
PageView.custom({
//...
@required this.childrenDelegate, //自定義模式接受一個(gè)子頁面委托對(duì)象
//...
})
這里主要以PageView.builder介紹一下PageView的使用
1、使用
//組件使用
PageView.builder(
itemBuilder: (context, index) {
return Center(
child: _getPageByIndex(index), //每個(gè)頁面展示的組件
);
},
itemCount: 4, //頁面數(shù)量
onPageChanged: _onPageChange, //頁面切換
controller: _pageController, //控制器
)
//返回每個(gè)頁面子組件
StatefulWidget _getPageByIndex(int index) {
switch (index) {
case 0:
return HomePage();
case 1:
return CategoryPage();
case 2:
return MeiZiPage();
case 3:
return AccountPage();
default:
return HomePage();
}
}
2、關(guān)于controller
PageController({
this.initialPage = 0, //初始化選擇頁面
this.keepPage = true, //是否保持已經(jīng)渲染過得頁面
this.viewportFraction = 1.0, //每個(gè)頁面應(yīng)占用的視口部分。 0~1之間
})
在是使用PageView的時(shí)候會(huì)包含一個(gè)默認(rèn)的控制器
var _pageController = PageController(initialPage: 0);
控制器跳轉(zhuǎn)有4個(gè)已有的方法
- animateToPage:帶動(dòng)畫跳轉(zhuǎn)
- jumpToPage:直接改變當(dāng)前頁面無動(dòng)畫
- nextPage:下一頁
- previousPage:上一頁
來先看看jumpToPage的效果
_pageController.jumpToPage(_selectedIndex);

jumpToPage
再看看animateToPage的效果,ps:切換時(shí)間500ms,切換效果Curves.easeInOut
_pageController.animateToPage(_selectedIndex,
duration: Duration(milliseconds: 500), curve: Curves.easeInOut);

animateToPage
3、PageController的viewportFraction
每個(gè)頁面應(yīng)占用的視口部分。 0~1之間,比如設(shè)置為0.8可以得到以下效果,直接上圖是最好的解釋。再加點(diǎn)自動(dòng)播放,循環(huán)播放之類的就是一個(gè)很nice的banner,但是這里只做demo演示,講解以下這個(gè)屬性,一般在flutter中banner不這樣做,這樣會(huì)有很多問題,比如拖拽時(shí)停止自動(dòng),pageView嵌套等問題。Flutter的概念里一切都是組件,banner組件我推薦輪子flutter_swiper
var _pageController = PageController(initialPage: 1, viewportFraction: 0.8);

viewportFraction: 0.8
4、配合BottomNavigationBar使用
關(guān)于BottomNavigationBar的使用可以參考我之前的
Flutter筆記(一):BottomNavigationBar常見問題
PageView和BottomNavigationBar聯(lián)動(dòng)的完整代碼如下
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
var _pageController = PageController(initialPage: 0);
void _incrementCounter() {
setState(() {
_selectedIndex++;
});
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
if (_pageController.hasClients) {
_pageController.animateToPage(_selectedIndex,
duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
// _pageController.jumpToPage(_selectedIndex);
}
}
void _onPageChange(int index) {
print("_onPageChange");
setState(() {
_selectedIndex = index;
});
}
StatefulWidget _getPageByIndex(int index) {
switch (index) {
case 0:
return HomePage();
case 1:
return CategoryPage();
case 2:
return MeiZiPage();
case 3:
return AccountPage();
default:
return HomePage();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
child: AppBar(
backgroundColor: Colors.white,
brightness: Brightness.light,
title: Center(
child: Text(
"FlutterDemo",
),
),
),
preferredSize: Size(double.infinity, 60)),
body: PageView.builder(
itemBuilder: (context, index) {
return Center(
child: _getPageByIndex(index), //每個(gè)頁面展示的組件
);
},
itemCount: 4, //頁面數(shù)量
onPageChanged: _onPageChange, //頁面切換
controller: _pageController, //控制器
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
bottomNavigationBar: new BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: new Icon(IconFont.iconhome), title: new Text("首頁")),
BottomNavigationBarItem(
icon: new Icon(IconFont.iconcategory), title: new Text("分類")),
BottomNavigationBarItem(
icon: new Icon(IconFont.iconpic), title: new Text("妹子")),
BottomNavigationBarItem(
icon: new Icon(IconFont.iconaccount), title: new Text("我的")),
],
selectedItemColor: Color(0xFF4CAF50),
unselectedItemColor: Color(0xff666666),
type: BottomNavigationBarType.fixed,
showUnselectedLabels: true,
onTap: _onItemTapped,
currentIndex: _selectedIndex,
selectedFontSize: 12.0,
),
);
}
}