本文適合Flutter初學者,沒有過多的深入內容,一起來感受flutter的魅力吧。
在原生安卓中,viewPager還是有一定難度的,通常我們要配合fragment及adapter使用,還要去管理fragment的生命週期。代碼量還是有的。
如何在flutter裏實現ViewPager呢?
答案很簡單,flutter爲我們封裝了一個PageView的Widget,只要善用它,就可以搞定了。
先來看最簡單的情況,我們的Page均爲Image的情況,而且我們不需要監聽事件,僅僅是用戶可以滑動,展示。
先把Flutter的模版寫好。
import 'package:flutter/material.dart';
void main() {
runApp(ViewPager());
}
class ViewPager extends StatelessWidget {
}
class ViewPagerStateful extends StatefulWidget {
}
class ViewPagerState extends State<ViewPagerStateful> {
}
順序如下,main函數創建ViewPager,ViewPager中代碼創建ViewPagerStateFul,ViewPagerStateFul中創建ViewPagerState,通過ViewPagerState改變狀態。在這裏,我們不需要改變ViewPager的狀態,所以ViewPagerStateful應該繼承於StatelessWidget。
改繼承自然要改名,於是,我們的模版如下:
import 'package:flutter/material.dart';
void main() {
runApp(ViewPager());
}
class ViewPager extends StatelessWidget {
}
class ViewPagerStateless extends StatelessWidget {
}
根據上述的順序,我們開始往其中填寫代碼。
先填ViewPager,它就是我們的整個可見頁面。
class ViewPager extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "ViewPager",
theme: ThemeData(primaryColor: Colors.blue),
home: ViewPagerStateless(),
);
}
}
設置一個主題,幷包裹我們的ViewPagerStateless。
接下來就是重中之重了,使用PageView來創建我們的ViewPager。
class ViewPagerStateless extends StatelessWidget {
// 小米官網找的圖。嗯,來源,小米新出的cc。
var imgs = [
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-02.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-03.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-04.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-05.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-06.png"
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("ViewPager")),
body: PageView(
children: <Widget>[
Image.network(imgs[0]),
Image.network(imgs[1]),
Image.network(imgs[2]),
Image.network(imgs[3]),
Image.network(imgs[4]),
],
),
);
}
}
appBar用來設置標題欄。
Image.network的命名構造方法可以直接幫我們把網絡的圖片下載並顯示出來。
PageView也很容易,設置一下children的list,就可以顯示了。
目前的完整代碼如下:
import 'package:flutter/material.dart';
void main() {
runApp(ViewPager());
}
class ViewPager extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "ViewPager",
theme: ThemeData(primaryColor: Colors.blue),
home: ViewPagerStateless(),
);
}
}
class ViewPagerStateless extends StatelessWidget {
var imgs = [
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-02.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-03.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-04.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-05.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-06.png"
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("ViewPager")),
body: PageView(
children: <Widget>[
Image.network(imgs[0]),
Image.network(imgs[1]),
Image.network(imgs[2]),
Image.network(imgs[3]),
Image.network(imgs[4]),
],
),
);
}
}
run起來效果如下:
這時候,我們已經可以左右的滑動了,也會有回彈的效果。
當然了,我們肯定不能滿足這樣的一個靜態效果,所以,我們把ViewPagerStateless刪除掉,建立ViewPagerStateful。
在Flutter中,StatefulWidget是有狀態的小部件,StatelessWidget是無狀態的小部件,有狀態的小部件才能更新哦。
class ViewPagerStateful extends StatefulWidget {
@override
ViewPagerState createState() {
return ViewPagerState();
}
}
這是有狀態小部件標準寫法了。所有的信息,都存在於ViewPagerState中。
我們還是先來實現跟之前ViewPagerStateless一樣的效果。
class ViewPagerState extends State<ViewPagerStateful> {
var imgs = [
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-02.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-03.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-04.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-05.png",
"https://i1.mifile.cn/f/i/2019/micc9/summary/specs-06.png"
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("ViewPager")),
body: PageView(
children: <Widget>[
Image.network(imgs[0]),
Image.network(imgs[1]),
Image.network(imgs[2]),
Image.network(imgs[3]),
Image.network(imgs[4]),
],
),
);
}
}
run一下,就發現,跟之前的效果完全一樣。
接下來,我們要進行事件的監聽,和viewpager內容的更改。
翻看上面代碼發現,多數均爲模版代碼,僅有ViewPagerState內有很多內容。
所以,理所當然,點擊事件也要在ViewPagerState中處理。
在ViewPagerState中新建方法,用來處理點擊:
這裏要用setState這個Flutter提供給我們的用於變更數據的方法,若不寫這個包裹,則變化無效。
void changeImg(int pos) {
setState(() {
imgs[pos] = "https://i1.mifile.cn/f/i/2019/micc9/summary/specs-08.png";
});
}
在ViewPagerState中新建方法,用於監聽滑動頁面變更:
void onPageChanged(int pos) {
print("當前是第$pos頁");
}
接下來,改造ViewPagerState的build方法,用於關聯起來。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("ViewPager")),
body: PageView(
children: <Widget>[
Image.network(imgs[0]),
Image.network(imgs[1]),
Image.network(imgs[2]),
Image.network(imgs[3]),
GestureDetector(
onTap: () => changeImg(4), child: Image.network(imgs[4]))
],
onPageChanged: onPageChanged,
),
);
}
這裏說一下爲什麼要用() =>
這個是dart語法,若不用,則相當於直接執行changeImg(4)
,這樣會在我們並沒有點擊時就會調用,這是不符合要求的。
Image本身不含有點擊事件,需要用GestureDetector包裹。
這時候就可以run了。當我們切換頁面,log就會打印出來,點擊最後一頁的圖片就會更新圖片。