開篇
大家好,我是練習時長1年的Flutter練習生,渣渣法,喜歡寫bug,發雞湯,當吃播。
一晃眼,入坑Flutter已經一年的時間,Flutter Candies 全家桶也從我一個人到現在有八個人,專案也接近30個,收穫頗多,希望有更多的人能加入我們,一起製造更多好用的Flutter?。
Flutter Candies QQ群: 181398081,人還不多,但是很熱鬧。這是一個擺龍門陣的地方;可以求助現場大佬/觀眾的地方;也是可以互相學習共同進步的地方。
感恩
-
加入掘金跟入坑Flutter的時間一樣,也是一年了,感恩。單純的技術平臺,讓程式猿們都聚在一起,互相學習,共同進步。說它單純呢,它卻不那麼正經,有各種板塊(相親,摸魚,翻譯等等),我現在都把它當朋友圈用了,@all, 你今天收到了我的雞湯了嗎?
-
感恩抱過的大腿們(大部分都是喵頭像,是不是巧合),Vadaski ,JarvanMo,debuggerx,戀貓de小郭, wendux,低調,拉麵等等等。感謝大佬的幫助,這也是Flutter Candies建立的用意,希望也能幫助到其他人,為Flutter社群貢獻微薄之力。自己從大佬那裡學到了,然後可以告訴別人,別人又可以再傳遞給其他人,這樣社群才會越來越好。
Flutter Candies 介紹
這是一個集合了Flutter開發中常用的元件/外掛?的全家桶,大家可以很方便的整合到自己的專案當中,下面我按照作者來介紹Flutter Candies 的各個專案。篇幅會有點長,請準備好瓜子汽水坐好,開車了,滴滴滴滴滴。
AlexV525
從開始在群裡提需求,到可以在群裡解答問題 ;從一個養魚專業的學生,到入行Flutter崗位工作。4月份入群到現在,看到了他的變化,也看到?組織的意義。入坑之後就住在了Github上面。
OpenJMU校園應用
精美的校園App,整個應用的完成度非常高,功能完整,因為賬號許可權的問題,無法登入。如果你看到某個功能,可以去找這個功能的實現程式碼,找不到的話可以來群裡問問。
GitHub 專案
從0搭建的Flutter實戰專案,專案程式碼繼續更新中,感興趣的小夥可以關注, 掘金文章地址,跟著從0開始寫Flutter專案。
波紋擴散高斯模糊動畫
波紋擴散,並且帶高斯模糊,按鈕跳動效果,喜歡騷的童鞋可以收藏起來了。掘金文章地址
CrazyQ1
Flutter教程網的作者,這是一個Flutter全方面資訊的聚合網站.
Flutter版微信
從0搭建的Flutter版微信實戰專案,專案功能程式碼繼續更新中,感興趣的小夥可以關注他以及後續相關文章
入魔的冬瓜
最近剛入桶的兄弟,有責任心的開發者,對自己的專案會不斷進行優化,達到最完美的狀態
自定義日曆元件
主要功能
- 支援公曆,農曆,節氣,傳統節日,常用節假日
- 日期範圍設定,預設支援的最大日期範圍為1971.01-2055.12
- 禁用日期範圍設定,比如想實現某範圍的日期內可以點選,範圍外的日期置灰
- 支援單選、多選模式,提供多選超過限制個數的回撥和多選超過指定範圍的回撥。
- 跳轉到指定日期,預設支援動畫切換
- 自定義日曆Item,支援組合widget的方式和利用canvas繪製的方式
- 自定義頂部的WeekBar
- 根據實際場景,可以給Item新增自定義的額外資料,實現各種額外的功能。比如實現進度條風格的日曆,實現日曆的各種標記
- 支援周檢視的展示
- 支援月份檢視和星期檢視的展示與切換聯動
喜歡的小夥伴趕快收藏起來吧 掘金文章地址
Flutter筆記
公眾號 Flutter筆記作者, Flutter小能手,歡迎關注微信公眾號
Flutter 版本的網易雲音樂
學習Flutter的一個途徑就是模仿現有的App,在Flutter上面進行實現。這是一個從0搭建的網易雲音樂。大家可以跟隨著作者的思路一步步完成一個完整的Flutter專案。介面很舒服,功能持續更新中,大家快來收藏吧 掘金文章地址
仿微信長按彈出選單
目前最好用的仿微信聊天長按彈出框,喜歡微信風格的小夥伴記得收藏起來掘金文章地址
caijinglong
低調,老鄉,不能吃辣的四川人(偷笑.gif), 反正就很牛逼就是了。Flutter 小白鼠,任何新東西他都要去玩一下。我也跟著踩他填好的坑,在Flutter的路上一去不回。Pub 25個。。可怕。。都是高分作品
flutter_image_editor
flutter_image_editor可以說是低調為extended_image量身打造的原生外掛,支援旋轉裁剪翻轉,extended_image負責圖片編輯UI,flutter_image_editor提供原生裁剪圖片資料能力。由於dart image庫在處理圖片的效率問題,原生庫(期待純C++庫)就有了很大的優勢(大圖片可以有10倍速度的提升)。正是因為teamwork才能使flutter上面對於圖片編輯處理最終達到一個完美的狀態。
法的空間
法法,200,Flutter Candies ? 全家桶的樓主。在感受到大佬們的感化之後,也希望能幫助到更多的Flutter開發者。pub目前13個,屬於專案中比較常用的元件。
extended_nested_scroll_view
做專案遇到的第一個遇到的問題就是官方的NestedScrollView,各方求證以及檢視原始碼之後發現應該只是as design。如果你即將使用官方的NestedScrollView,強力建議先看一下,你必定會遇到下面的問題 掘金文章地址
問題1. NestedScrollView的Header中有鎖定(Pinned=true)的Sliver元件的時候,body的滾動問題
其實官方對這個是有處理的,是通過SliverOverlapAbsorber包裹SliverAppbar,程式碼不上了,其實NestedScrollView的註釋裡面就有.
但是問題在,於如果header裡面有多個pinned=true的sliver,我們該怎麼處理了?為此我擴充套件了官方的元件。你可以通過設定pinnedHeaderSliverHeightBuilder回撥來解決這個問題,在下面的程式碼中,pinnedHeaderHeight其實就是SliverAppbar最後摺疊起來之後高度=狀態列高度+導航欄高度.如果你header中有其他鎖定的sliver,你可以再把它們的高度加進去。
var pinnedHeaderHeight =
//statusBar height
statusBarHeight +
//pinned SliverAppBar height in header
kToolbarHeight;
return NestedScrollView(
pinnedHeaderSliverHeightBuilder: () {
return pinnedHeaderHeight;
},
複製程式碼
問題2. NestedScrollView的body中TabView裡面的列表會滾動同步互相影響
由於NestedScrollView內部裡面有一個ScrollController,TabView裡面的列表的ScrollPosition都將會attach到這個sc上面,在滾動其中一個的時候,同步全部的ScrollPositions。由於篇幅原因,我這裡直接放之前的文章了。
問題3. 不能給body裡面的列表設定ScrollController
由於body裡面的列表必須共用同一個ScrollController,所以你是不能給列表單獨設定ScrollController。如果設定了會導致內部的outer_scroll_controller和inner_scroll_controller無法協同工作。
大家想使用ScrollController無非3點。
1.下拉重新整理,已提供demo
2.載入更多,已提供demo
3.控制列表滾動,已將屬性暴露出來
使用常見問題
- 元件名字跟官方相同,所以當你們使用的時候,記住遮蔽掉官方的(太大膽了)
import 'package:flutter/widgets.dart' hide NestedScrollView;
複製程式碼
- 對NestedScrollView不熟悉 這個建議先百度下,熟悉了官方的使用方式之後,再來看這些官方未解決的問題。
extended_image
Flutter上面最能打的圖片庫(這樣說沒人打我吧) 掘金文章地址
主要功能
- 快取網路圖片
- 載入狀態(正在載入,完成,失敗)
- 拖拽縮放圖片
- 圖片編輯(裁剪,旋轉,翻轉)
- 圖片預覽(跟微信掘金一樣)
- 滑動退出效果(跟微信掘金一樣)
- 設定圓角,邊框
使用常見問題
- 載入狀態如何重寫
設計原則是,如果你需要重寫一個狀態,就返回你想要的效果,否則請返回null。下面是一個重寫“正在載入”的例子
ExtendedImage.network(
item.imageUrl,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container();
}
return null;
},
);
複製程式碼
很多人因為在重寫了completed狀態而丟失了手勢和裁剪功能,為此我新增了ExtendedImageState.completedWidget。下面是重寫completed狀態而不丟失裁剪手勢功能的例子。
ExtendedImage.network(
item.imageUrl,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.completed) {
return Padding(
padding: EdgeInsets.all(10.0),
child: state.completedWidget,
);
}
return null;
},
);
複製程式碼
- path_provider外掛混合開發問題
請自行檢視issue
extended_image_library
extended_image的基礎庫,如果你只需要網路圖片快取功能,你可以只引用這個庫
Image(
image: ExtendedNetworkImageProvider("", cache: true),
);
複製程式碼
extended_text
富有中國特色強大功能的富文字 掘金文章地址
主要功能
- 快速構建富文字
- 支援選擇(包括WidgetSpan)以及自定義選單
- 支援溢位文字自定義
- 支援自定義背景
使用常見問題
- SpecialTextSpanBuilder的使用
為了快速構建富文字,比如把 '[love]' 這種文字變成表情圖片,提供了SpecialTextSpanBuilder。其原理很簡單,就是根據你自己的規則,將文字轉換成各種InlineSapn(TextSpan,ImageSpan,WidgetSpan).
這裡build方法是用入棧的方式遍歷文字,createSpecialText方法是用來根據你自己的規則建立SpecialText的。有一些使用者可能覺得太複雜了,但是我這樣考慮就是為了大家能根據自己業務的需求來自定義自己的規則。耐心看懂demo,你可以快速的自定義自己的富文字
abstract class SpecialTextSpanBuilder
{
TextSpan build(String data,
{TextStyle textStyle, SpecialTextGestureTapCallback onTap})
SpecialText createSpecialText(String flag,
{TextStyle textStyle, SpecialTextGestureTapCallback onTap, int index});
}
複製程式碼
extended_text_field
Flutters上面唯一能支援輸入內容是WidgetSpan的輸入框 掘金文章地址
主要功能
- 快速構建富文字
- 支援選擇(包括WidgetSpan)以及自定義選單
仿掘金推特點贊按鈕
仿掘金推特點贊按鈕,帶數量滾動動畫掘金文章地址
下拉重新整理
可以在任何滾動場景中使用(包括NestedScrollView)的自定義下拉重新整理元件, 只提供了下拉重新整理的狀態,你可以最大化的自定義自己的效果而不用拘泥於元件本身提供。你可以根據狀態距離,構建出任何你想要的效果。demo裡面的4種效果只是例子,歡迎大家pr更多更有趣的效果。掘金文章地址
使用常見問題
- 不滿一螢幕,無法下拉重新整理
- iOS Bouncing 效果影響下拉重新整理
這2個問題都可以通過設定列表的physics來解決,我這裡提供了AlwaysScrollableClampingScrollPhysics。
///in case list is not full screen and remove ios Bouncing
class AlwaysScrollableClampingScrollPhysics extends ClampingScrollPhysics {
const AlwaysScrollableClampingScrollPhysics({ScrollPhysics parent})
: super(parent: parent);
@override
AlwaysScrollableClampingScrollPhysics applyTo(ScrollPhysics ancestor) {
return AlwaysScrollableClampingScrollPhysics(parent: buildParent(ancestor));
}
@override
bool shouldAcceptUserOffset(ScrollMetrics position) {
return true;
}
}
複製程式碼
擴充套件列表
支援特殊佈局,記憶體清除以及可視區域Indexes變化追蹤。更多詳情
回收圖片快取
collectGarbage: (List<int> indexes) {
///collectGarbage
indexes.forEach((index) {
final item = listSourceRepository[index];
if (item.hasImage) {
item.images.forEach((image) {
final provider = ExtendedNetworkImageProvider(
image.imageUrl,
);
provider.evict();
});
}
});
},
複製程式碼
瀑布流
高效能的瀑布流佈局,喜歡的瀑布流的小夥伴趕快收藏起來。
列表載入更多
繼承了UWP的載入更多思想的作品,將UI跟資料來源的契約完美打通,你只要寫過一次,你就會愛上這種方式,新增支援瀑布流。掘金文章地址
extended_tabs
支援TabBarView的聯動,就是說二級TabBarView不能滑動了,就看一級能不能滑動,能滑動就滑動一級的 掘金文章地址
路由註解
輕巧靈活的路由註解工具,一行命令完成路由對映. 掘金文章地址
Json轉換Dart實體類工具
使用C#以及Flutter構建的json轉換dart實體類工具,提供超級多的平臺選擇,大氣的ui介面(偷笑.gif) 掘金文章地址
平臺 | 語言 | 描述 | 程式碼/安裝包地址 |
---|---|---|---|
windows | C# | uwp構建,執行環境windows10,x86/x64 | windows-uwp.zip |
windows | C# | wpf構建,執行環境windows10/windows8/widnows7,x86/x64 | windows-wpf.zip |
windows | dart | flutter構建, 使用官方方式編譯,x64 ,debug版本 | windows-x64-flutter.zip |
windows | dart | flutter構建, 使用go-flutter編譯,x64 ,debug版本 | windows-x64-go-flutter.zip |
mac | dart | flutter構建,使用go-flutter編譯(官方方式,未找到產物) | mac-go-flutter.zip |
web | C# | silverlight構建, 需要安裝silverlight外掛,有瀏覽器限制 | 網頁地址和帶字型檔案網頁地址 |
web | dart | flutter-web構建 | 網頁地址 |
linux | dart | flutter構建, 使用官方方式編譯,(沒有環境測試,假裝可以用) | 程式碼地址 |
Flutter常見問題
從哪裡上手Flutter
Flutter中國官方網站,Flutter官方明媒正娶,從入門到深入,各種資源應有盡有。如果你準備入手Flutter,這應該是你必看的網站。
萌新問問題
每個人都從萌新而來,如果你想開森的寫程式碼,自己解決問題是必須的
-
英語是很重要的。
-
問問題的時候,儘量上程式碼,或者說明你的意圖,因為可能你的想法或者解決方向就是錯誤的
-
如果實在無法自己解決,可以求助於大佬,但是請注意提問方式,畢竟好溝通能節約雙方的時間,大佬也要工作也要吃飯。
怎麼找外掛
把你的想要效果的外掛的名字或者其他平臺的元件叫什麼名字,轉為為英文,到pub 上面搜尋,分高的使用的人多,相對就比較穩定更好。
安卓下載各種東西慢
我們經常執行別人元件的時候,發現各種下載失敗,各種下載緩慢 請使用國內映象,飛一般的趕腳。
- 替換google()和jcenter()
google()
jcenter()
替換為下面
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
- 替換grade下載地址 將上面的替換成下面映象
#distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
#csdn映象
distributionUrl=https\://downloads.gradle-dn.com/distributions/gradle-5.1.1-all.zip
複製程式碼
為啥設定Size沒有效果
在開發中,我們發現給元件設定了大小,但是卻沒有效果。舉個栗子,在Appbar的leading/actions中,我們想直接設定寬高是不可能的。 我們需要使用UnconstrainedBox來移除父widget對子大小的限制,如下程式碼
AppBar(
title: Text(widget.title),
leading: UnconstrainedBox(
child: Container(
width: 50.0,
height: 10.0,
color: Colors.red,
),
),
),
複製程式碼
鍵盤彈出的時候,怎麼把佈局頂上去,而不遮住佈局
- 通過下面程式碼獲取鍵盤高度(放心鍵盤彈出或者收起的時候都會觸發build)
double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
複製程式碼
- 然後你的佈局大概就是下面這樣
Column(
children: <Widget>[
///你的佈局
Expanded(
child: Container(),
),
///頂起你的佈局
Container(
height: keyboardHeight,
)
],
);
複製程式碼
其實這個我也是在原始碼裡面scaffold.dart中看到的,抄作業很重要
關鍵程式碼
並且在_ScaffoldLayout中增加了這個高度pub.dev 慢,打不開?!
中國映象你在等什麼呢,學起來
國際化之後設定hintText,游標位置不一致
issue地址 通過設定下面程式碼解決,全域性設定文字主題
textTheme: theme.textTheme.copyWith(
subhead: theme.textTheme.subhead
.copyWith(textBaseline: TextBaseline.alphabetic)),
複製程式碼
我的文字設定了溢位,為啥沒有效果
我們經常聽到的就是為什麼我的文字設定了溢位顯示,但是它卻顯示黃色溢位警告了? 對於文字Text來說,如果它的父Widget沒有給它做大小限制,它預設是無限長的 我們解決的方法如下。
- 給它設定個大小,如果無效請參考 為啥設定Size沒有效果 (特別注意,Row/Column巢狀的時候。你需要從最外面一層就給內層限定大小,參考下面一條)
- Row/Column中,給它設定Expaned/Flexible 這樣告訴文字,你的大小是,其他widget剩下的那空間。 Expaned/Flexible都有這個作用,但是它們的區別是什麼呢。給你們看2張圖你就明白了。
return Row(
children: <Widget>[
Flexible(
child: Text(
"我是一個很短的文字",
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12),
),
),
Container(
color: Colors.red,
width: 100.0,
)
],
);
複製程式碼
return Row(
children: <Widget>[
Expanded(
child: Text(
"我是一個很短的文字",
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12),
),
),
Container(
color: Colors.red,
width: 100.0,
)
],
);
複製程式碼
Expaned/Flexible 兩者的區別就在於,Expanded會強制佔100剩餘的空間,而Flexible可以自適應。當然他們最大也都是佔100剩餘的空間。
獲取滾動元件中孩子的位置
更多的細節,你可以檢視文章
官方的Appbar不好用
由於官方的Appbar增加了對material風格的設定,所以很多地方都有一些限制。其實也不能怪官方,這是一種設計規範。但是我們就是想自己騷怎麼辦呢?? 我之前寫了個 my_app_bar.dart,之前一直放gists上面,不方便大家檢視,現在也移入了?。這是一個簡單的實現,看明白了程式碼原理之後,你可以擴充套件出更多適合自己的appbar。
掘金斗魚的那種首頁滾動效果怎麼做?
因為有好幾個人問過,所以我寫了個簡單的demo。主要是靠NotificationListener來監聽滾動來控制頭部。
黃色警告 ⚠ 一定要管嗎?
不是每一種警告,都是一定要管的。警告只是官方告訴你需要注意這點,這就是為什麼Release下面不會出現警告。警告不等於錯誤。
我這裡舉一個栗子。NestedScrollView的body其實是SliverFillRemaining包住的,它會跟著一起滾動。但是我們這裡佈局裡面是一個Tabbar,它是一個有固定高度的元件,當它超出螢幕的時候就會出現警告。但是事實上,這種警告並不能影響我們的使用。
push/pop的時候頁面重新build
如果你是因為頁面重新build就影響你的業務,那應該好好檢查下業務邏輯程式碼。build的原因是route變化時候的動畫,以及NavigatorState中Overlay(實際就是Stack),route位置變化而引起的頁面build。
ListView巢狀,shrinkWrap 的使用
Listview裡面巢狀Listview,是我經常看到過的,會報錯。然後就會有人說 把這個設定成shrinkWrap 設定成true。下面我們來看看這個屬性的意思。
/// Whether the extent of the scroll view in the [scrollDirection] should be determined by the contents being viewed.
///
/// If the scroll view does not shrink wrap, then the scroll view will expand to the maximum allowed size in the [scrollDirection]. If the scroll view has unbounded constraints in the [scrollDirection], then [shrinkWrap] must be true.
///
/// Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.
///
/// Defaults to false.
final bool shrinkWrap;
複製程式碼
-
設定shrinkWrap為true,scrollview的範圍將是全部內容的高度,否則是為viewport的高度。列表或者說ScrollView其實有一個可視區域的概念(Viewport),就是滾動時候的可見的部分,這個區域的大小往往需要你自己告訴他或者它的父親告訴它,超出這個範圍的內容會根據情況進行回收。
-
我們這裡看到為什麼直接使用Listview巢狀Listview會報錯了。因為Listview本身是無高度限制的,而你把一個Listview放在一個Listview裡面,裡面的Listview的viewport是無從得知的。那怎麼辦呢? 那隻能使用設定shrinkWrap為true,讓裡面的Listview的高度其實等於自己全部內容的高度。這樣外面Listview就能知道這個孩子的高度了。
-
設定shrinkWrap為true,更消耗效能。因為在滾動的時候都需要重新去計算高度是否變化。並且不會回收可視區域之外的內容。
-
使用ListView巢狀Listview的場景往往都能使用Sliver系列來解決,詳情請看下一個問題
Sliver 一生之敵?一生之愛?
群裡萌萌說的時候,我有點驚訝道,但是Sliver確實是經常有人問到的。Sliver系列的東東很多,我們下面來一一介紹一下。
-
CustomScrollView 是Sliver元件的老祖宗,全部的Sliver都放在這個裡面,大家別看ListView/GridView跟他們不一樣,其實裡面還是Sliver系列,只是不能將他們直接放到Sliver裡面,也不建議這樣做。
-
NestedScrollView這個也是大家經常使用到的,其實裡面是一個CustomScrollView,它的headers是Sliver的陣列,body是被包裹在 SliverFillRemaining 中的
-
SliverList 列表跟ListView用法差不多,跟CustomScrollView一起使用
-
SliverFixedExtentList, 比SliverList多一個就是相同的Extent,這樣效能會更好,跟CustomScrollView一起使用
-
SliverPrototypeExtentList 主軸上面有相同的Extent,跟SliverFixedExtentList靈活,不需要設定Extend,而是根據prototypeItem來獲取Extent
-
SliverGrid, 可以設定每行的個數的Grid,跟CustomScrollView一起使用
-
SliverPadding,跟Padding一樣的使用,區別是child變成了sliver
SliverPadding(
sliver: SliverList(),
padding: EdgeInsets.all(5.0),
);
複製程式碼
-
SliverPersistentHeader 非常好用的元件,SliverAppBar就是用這個實現的。這個元件的特點是可以建立出隨著滑動變化的可以Pinned的元素,大家經常用的什麼吸頂元件可以用這個很方便的構建,前面講到的自定義SliverAppbar(my_app_bar.dart)就是利用它實現的。
-
SliverAppBar 跟Appbar的最大區別就可以根據滾動狀態來摺疊內容,主要是由狀態列高度+導航欄高度+摺疊高度組成
-
SliverToBoxAdapter 當你想把一個非Sliver的Widget放在CustomScrollview裡面的時候,你需要用這個包裹一下。
-
SliverSafeArea 為了防止各種邊界的越界,比如說越過頂部的狀態列
-
SliverFillRemaining使用這個它會填充完viewport裡面的剩餘全部空間。NestedScrollView的body就是這個包裹住的。
-
SliverOverlapAbsorber,SliverOverlapAbsorberHandle 這個是關於NestedScrollView 解決Pinned頭部的,這裡不贅述,我前面也講的有。
其實Sliver系列沒有那麼可怕,如果你弄懂每一個Sliver的使用場景,你可以完成其他平臺可能需要很費勁才能做出來的效果。下面舉一些常用的栗子吧。
- Listview巢狀ListView 這種大部分情況可以用下面程式碼代替。
return CustomScrollView(
slivers: <Widget>[
SliverList(),
SliverList(),
],
);
複製程式碼
如果你是水平垂直巢狀的話,可以設定內部那個Listview的高度或者寬度
return ListView(
children: <Widget>[
SizedBox(
height: 60.0,
child: ListView.builder(
itemBuilder: (c, index) {}, scrollDirection: Axis.horizontal),
)
],
);
複製程式碼
- 主流App首頁帶滾動頭
注意這個NestedScrollView不是官方的,是我擴充套件的。詳細情況請看上面
///因為SliverAppBar是pinned:true,所以我們需要算上這部分高度
var pinnedHeaderHeight =
//statusBar height
statusBarHeight +
//pinned SliverAppBar height in header
kToolbarHeight;
return NestedScrollView(
pinnedHeaderSliverHeightBuilder: () {
return pinnedHeaderHeight;
},
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled)
{
return <Widget>[
SliverAppBar(pinned:true),
//可是banner,也可以是廣告位之類的
SliverToBoxAdapter(),
//當然可以個列表
SliverList(),
//我們也可以在這裡建立可以吸頂的內容
//如果這個是pinned等於true的,記得把這部分高度增加到pinnedHeaderHeight當中
SliverPersistentHeader()
];
},
body: Column(
children: <Widget>[
///最終Tabbar會被Pinned在SliverAppbar(pinned:true)下面。
///當然,比如說sliverappbar下面 有另外一個pinned為ture的 ///sliver。那邊tabbar最後會在這個pinned ///true的sliver下面。(總的pinnedHeaderHeight高度應該是(狀///態欄高度+導航欄高度=pinned為true的SliverAppbar)+pinne///d為ture的Sliver的高度)
TabBar(),
Expanded(
child: TabBarView(),
)
],
),
);
複製程式碼
- 分組的列表
這樣寫的一個好處,內容可以被回收,效能好。
return CustomScrollView(
slivers: <Widget>[
//分組頭部1,
SliverToBoxAdapter(),
//分組1
//分組2
當然我們在SliverList的第一item裡面特殊處理下,增加分組頭
SliverList(),
SliverList(delegate: SliverChildBuilderDelegate((c, index) {
///item 內容
Widget item = Container();
if (index == 0) {
item = Column(
children: <Widget>[
///分組2頭部
Container(),
item
],
);
}
return item;
})),
],
);
複製程式碼
當然栗子是舉不完的,但是當你學會使用之後,終於有一天,一生之敵會變成你的一生之愛的。
其他常見問題
結語
-
如果你堅持看到這裡,真愛啊,快加入小糖果吧 QQ群: 181398081。我們這裡有吃瓜群眾,保安,門衛,祕書,群花,大佬,感謝他們的默默付出。如果你是喜歡分享的,請加入我們;如果你需要分享的,也請加入我們。
-
入坑Flutter的一年,除了工作時間之外,業餘時間也付出很多在Flutter上面。有時候做一個東西,思路來了,可能會肝到凌晨4,5點。我倒不是提倡這種,程式猿還是要注意自己的身體,身體才是寫程式碼的本錢。但是我們如果每天睡覺之前能擠出1小時來學習下,一年就是365小時=15天,相信收穫還是很大的。給自己定義一個小目標,一步一步的完成。
-
最後展望一下明年的Flutter。期待熱更新,web效能提升,以及對C++更好的支援。