Flutter實(shí)現(xiàn)App功能引導(dǎo)頁(yè)
App功能介紹頁(yè),主要是由介紹app功能的幾張圖片和當(dāng)前頁(yè)指示符組成,如下效果

我們來(lái)一步一步實(shí)現(xiàn)上面的界面,左右滑動(dòng)切換顯示功能頁(yè),這個(gè)可以通過(guò)PageView來(lái)實(shí)現(xiàn),底部的指示符半透明覆蓋在PageView上,開(kāi)發(fā)過(guò)Android同學(xué)知道可以用Framelayout布局來(lái)實(shí)現(xiàn),F(xiàn)lutter上也有類似的控件Stack,我們先完成骨架代碼
// An highlighted block
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AppFuncBrowse(),
);
}
}
class AppFuncBrowse extends StatefulWidget {
@override
_AppFuncBrowseState createState() {
return _AppFuncBrowseState();
}
}
class _AppFuncBrowseState extends State<AppFuncBrowse> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Stack(
children: <Widget>[
],
),
));
}
}
AppFuncBrowse 就是我們功能介紹頁(yè),上面編譯運(yùn)行功能后,我們先來(lái)著手實(shí)現(xiàn)功能介紹頁(yè)面切換,PageView主要有兩類構(gòu)建函數(shù),一個(gè)是懶加載頁(yè)面(適合頁(yè)面很多時(shí)使用),一個(gè)是適合少量頁(yè)面的一次性加載的,我們實(shí)例顯示3個(gè)頁(yè)面,就簡(jiǎn)單的用這種方式, PageView用到了PageController用來(lái)控制顯示哪一頁(yè),先定義它
class _AppFuncBrowseState extends State<AppFuncBrowse> {
PageController _pageController = PageController();
//省略...
}
有了PageController我們就可以創(chuàng)建PageView,代碼如下
Widget _createPageView() {
return PageView(
controller: _pageController,
onPageChanged: (pageIndex) {
setState(() {
_pageIndex = pageIndex;
print(_pageController.page);
print(pageIndex);
});
},
children: <Widget>[
Container(
color: Colors.blue,
child: Center(
child: Text('Page 1'),
),
),
Container(
color: Colors.red,
child: Center(
child: Text('Page 2'),
),
),
Container(
color: Colors.green,
child: Center(
child: Text('Page 3'),
),
),
],
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Container(
color: Colors.white,
// margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Stack(
children: <Widget>[
_createPageView(),
],
),
));
}

到這里我們完成了一個(gè)可以左右滑動(dòng)的功能頁(yè), 每頁(yè)的內(nèi)容大家可以自定義,一般是一張圖片,我這里為了簡(jiǎn)單起見(jiàn)直接顯示Text,到目前為止我們離目標(biāo)還缺一個(gè)頁(yè)碼指示器,學(xué)過(guò)iOS的非常熟悉,需要用到UIPageControl,可惜的是到目前為止Flutter還沒(méi)提供該原生控件,我們只能自己實(shí)現(xiàn)它,其實(shí)也很簡(jiǎn)單,代碼如下:
_createPageIndicator() {
return Opacity(
opacity: 0.7,
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: 60),
height: 40,
width: 80,
padding: EdgeInsets.all(0),
decoration: BoxDecoration(
color: Colors.grey, //.withAlpha(128),
borderRadius: BorderRadius.all(const Radius.circular(6.0))),
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTapUp: (detail) => _handlePageIndicatorTap(detail),
child: Row(
key: _pageIndicatorKey,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_dotWidget(0),
_dotWidget(1),
_dotWidget(2),
]),
),
),
),
);
}
咋一看感覺(jué)好復(fù)雜,其實(shí)也很簡(jiǎn)單,學(xué)過(guò)設(shè)計(jì)模式的同學(xué)可能看出和裝飾者模式一樣,widget層次結(jié)構(gòu)就類似這種模式,這也是Flutter的強(qiáng)大之處,用現(xiàn)有的控件可以組合出各種效果,首先我們用Opacity控件來(lái)封裝子控件,設(shè)置opacity使其成為半透明,然后使用Align控制其底部對(duì)齊,為了使其距離底部一段距離,還需要Container來(lái)包裝,為了實(shí)現(xiàn)圓角的Container,強(qiáng)大的decoration屬性就登場(chǎng)了,它能實(shí)現(xiàn)各種裝飾效果,這里我們實(shí)現(xiàn)的效果是灰色背景和圓角。
現(xiàn)在講完了這些裝修,就剩下三個(gè)點(diǎn)了,三個(gè)點(diǎn)在同一水平線上,所以我們用Row來(lái)做為父控件,Row有幾個(gè)屬性值注意
mainAxisAlignment 主軸對(duì)齊方式,Row的主軸是水平方向,
crossAxisAlignment 主軸的垂直方向?qū)R方式,Row的主軸是水平方向,所以該字段表示上下對(duì)齊方式
mainAxisSize 主軸方向的大小,對(duì)Row來(lái)說(shuō)即寬度
與Row對(duì)應(yīng)的控件是Column,其對(duì)應(yīng)上面屬性剛好相反
上面屬性的其他值可以自己試驗(yàn),我們這里用到
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min,
表示子控件左右(包含與父控件)間距相同,并且寬度保持最小,最后我們來(lái)實(shí)現(xiàn)三個(gè)點(diǎn),當(dāng)前頁(yè)的對(duì)應(yīng)的點(diǎn)顏色需要和其他未顯示的頁(yè)有所區(qū)別,我們需要記錄當(dāng)前是第幾頁(yè),從而使對(duì)應(yīng)的第幾個(gè)點(diǎn)highlight顯示
class _AppFuncBrowseState extends State<AppFuncBrowse> {
PageController _pageController = PageController();
int _pageIndex = 0;
然后就可以創(chuàng)建點(diǎn)了
_dotWidget(int index) {
return Container(
width: 10,
height: 10,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (_pageIndex == index) ? Colors.white70 : Colors.black12));
}
滑動(dòng)PageView,需要更新_pageIndex,從而對(duì)應(yīng)的更新當(dāng)前頁(yè)對(duì)應(yīng)的點(diǎn)的顏色
return PageView(
controller: _pageController,
onPageChanged: (pageIndex) {
setState(() {
_pageIndex = pageIndex;
print(_pageController.page);
print(pageIndex);
});
},
onPageChanged就是PageView換頁(yè)的事件,這里需要調(diào)用setState從而使Widget重建更新當(dāng)前頁(yè)的點(diǎn)顏色
到這里為止就剩下點(diǎn)擊點(diǎn)更新PageView的功能了,我們來(lái)實(shí)現(xiàn)點(diǎn)擊功能,就是監(jiān)聽(tīng)點(diǎn)擊手勢(shì),代碼如下
_handlePageIndicatorTap(TapUpDetails detail) {
RenderBox renderBox =
_pageIndicatorKey.currentContext.findRenderObject();
Size widgeSize = renderBox.paintBounds.size;
Offset tapOffset =
renderBox.globalToLocal(detail.globalPosition);
if (tapOffset.dx > widgeSize.width / 2) {
_scrollToNextPage();
} else {
_scrollToPreviousPage();
}
}
手勢(shì)有一個(gè)屬性behavior需要值得注意,默認(rèn)值為deferToChild,具體取值如下:
behavior: HitTestBehavior.translucent 控制響應(yīng)的點(diǎn)擊區(qū)域:
translucent 表示整個(gè)區(qū)域,被遮擋的子視圖也能響應(yīng)
opaque 表示整個(gè)區(qū)域,被遮擋的子視圖不能響應(yīng)
deferToChild 表示點(diǎn)擊到子視圖才響應(yīng),手勢(shì)默認(rèn)behavior
需要實(shí)現(xiàn)點(diǎn)擊左半部分向前翻頁(yè),點(diǎn)擊后半部分向后翻頁(yè),我們需要判斷當(dāng)前點(diǎn)擊的區(qū)域,這就需要找到Row的RenderObject來(lái)獲取控件區(qū)域,然后獲取點(diǎn)擊相對(duì)控件的偏移來(lái)確定,具體見(jiàn)代碼,_pageIndicatorKey就是傳給Row的key,具體定義如下
class _AppFuncBrowseState extends State<AppFuncBrowse> {
PageController _pageController = PageController();
int _pageIndex = 0;
GlobalKey<_AppFuncBrowseState> _pageIndicatorKey = GlobalKey();
現(xiàn)在只剩下前后翻頁(yè)的代碼了,代碼如下
_scrollToPreviousPage() {
if (_pageIndex > 0) {
_pageController.animateToPage(_pageIndex - 1,
duration: const Duration(milliseconds: 200), curve: Curves.ease);
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android如何在原生App中嵌入Flutter
- Flutter沉浸式狀態(tài)欄/AppBar導(dǎo)航欄/仿咸魚(yú)底部凸起導(dǎo)航欄效果
- Flutter以兩種方式實(shí)現(xiàn)App主題切換的代碼
- flutter 怎么實(shí)現(xiàn)app整體灰色效果
- Flutter 實(shí)現(xiàn)整個(gè)App變?yōu)榛疑姆椒ㄊ纠?/a>
- Flutter 滾動(dòng)監(jiān)聽(tīng)及實(shí)戰(zhàn)appBar滾動(dòng)漸變的實(shí)現(xiàn)
- 如何使用Flutter開(kāi)發(fā)一款電影APP詳解
- flutter BottomAppBar實(shí)現(xiàn)不規(guī)則底部導(dǎo)航欄
- Flutter下載更新App的方法示例
- Flutter 如何設(shè)置App的主色調(diào)與字體
相關(guān)文章
Android中WebChromeClient和WebViewClient的區(qū)別淺析
這篇文章主要介紹了Android中WebChromeClient和WebViewClient的區(qū)別淺析,需要的朋友可以參考下2015-04-04
Android實(shí)現(xiàn)自適應(yīng)屏幕的彈窗廣告
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)自適應(yīng)屏幕的彈窗廣告,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
ListView滑動(dòng)隱藏顯示ToolBar的實(shí)例
下面小編就為大家分享一篇ListView滑動(dòng)隱藏顯示ToolBar的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android仿淘寶詳情頁(yè)面viewPager滑動(dòng)到最后一張圖片跳轉(zhuǎn)的功能
需要做一個(gè)仿淘寶客戶端ViewPager滑動(dòng)到最后一頁(yè),再拖動(dòng)的時(shí)候跳到詳情的功能,剛開(kāi)始我也迷糊了,通過(guò)查閱相關(guān)資料發(fā)現(xiàn)有好多種實(shí)現(xiàn)方法,下面小編給大家分享實(shí)例代碼,感興趣的朋友一起看看吧2017-03-03
Android?Xml轉(zhuǎn)換為View過(guò)程詳解
這篇文章主要為大家介紹了Android?Xml轉(zhuǎn)換為View實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Android實(shí)現(xiàn)本地上傳圖片并設(shè)置為圓形頭像
我們?cè)谧鲰?xiàng)目的時(shí)候會(huì)用到圓形的圖片,比如用戶頭像,類似QQ。用戶在用QQ更換頭像的時(shí)候,上傳的圖片都是矩形的,但顯示的時(shí)候確是圓形的。那么這是如何實(shí)現(xiàn)的呢,下面我們就來(lái)探討下吧。2015-05-05
Android Shader應(yīng)用開(kāi)發(fā)之霓虹閃爍文字效果
這篇文章主要為大家詳細(xì)介紹了Android Shader應(yīng)用開(kāi)發(fā)之霓虹閃爍文字效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Android WebView線性進(jìn)度條實(shí)例詳解
這篇文章主要介紹了Android WebView線性進(jìn)度條實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-01-01

