你們好,我是練習時長1年的Flutter練習生,渣渣法,喜歡寫bug,發雞湯,當吃播。html
一晃眼,入坑Flutter已經一年的時間,Flutter Candies 全家桶也從我一我的到如今有八我的,項目也接近30個,收穫頗多,但願有更多的人能加入咱們,一塊兒製造更多好用的Flutter🍬。linux
Flutter Candies QQ羣: 181398081,人還很少,可是很熱鬧。這是一個擺龍門陣的地方;能夠求助現場大佬/觀衆的地方;也是能夠互相學習共同進步的地方。ios
加入掘金跟入坑Flutter的時間同樣,也是一年了,感恩。單純的技術平臺,讓程序猿們都聚在一塊兒,互相學習,共同進步。說它單純呢,它卻不那麼正經,有各類板塊(相親,摸魚,翻譯等等),我如今都把它當朋友圈用了,@all, 你今天收到了個人雞湯了嗎?git
感恩抱過的大腿們(大部分都是喵頭像,是否是巧合),Vadaski ,JarvanMo,debuggerx,戀貓de小郭, wendux,低調,拉麪等等等。感謝大佬的幫助,這也是Flutter Candies建立的用意,但願也能幫助到其餘人,爲Flutter社區貢獻微薄之力。本身從大佬那裏學到了,而後能夠告訴別人,別人又能夠再傳遞給其餘人,這樣社區纔會愈來愈好。github
這是一個集合了Flutter開發中經常使用的組件/插件🍬的全家桶,你們能夠很方便的集成到本身的項目當中,下面我按照做者來介紹Flutter Candies 的各個項目。篇幅會有點長,請準備好瓜子汽水坐好,開車了,滴滴滴滴滴。web
從開始在羣裏提需求,到能夠在羣裏解答問題 ;從一個養魚專業的學生,到入行Flutter崗位工做。4月份入羣到如今,看到了他的變化,也看到🍬組織的意義。入坑以後就住在了Github上面。 json
精美的校園App,整個應用的完成度很是高,功能完整,由於帳號權限的問題,沒法登陸。若是你看到某個功能,能夠去找這個功能的實現代碼,找不到的話能夠來羣裏問問。 canvas
從0搭建的Flutter實戰項目,項目代碼繼續更新中,感興趣的小夥能夠關注, 掘金文章地址,跟着從0開始寫Flutter項目。windows
波紋擴散,而且帶高斯模糊,按鈕跳動效果,喜歡騷的童鞋能夠收藏起來了。掘金文章地址api
最近剛入桶的兄弟,有責任心的開發者,對本身的項目會不斷進行優化,達到最完美的狀態
主要功能
喜歡的小夥伴趕快收藏起來吧 掘金文章地址
公衆號 Flutter筆記做者, Flutter小能手,歡迎關注微信公衆號
學習Flutter的一個途徑就是模仿現有的App,在Flutter上面進行實現。這是一個從0搭建的網易雲音樂。你們能夠跟隨着做者的思路一步步完成一個完整的Flutter項目。界面很舒服,功能持續更新中,你們快來收藏吧 掘金文章地址
目前最好用的仿微信聊天長按彈出框,喜歡微信風格的小夥伴記得收藏起來掘金文章地址
低調,老鄉,不能吃辣的四川人(偷笑.gif), 反正就很牛逼就是了。Flutter 小白鼠,任何新東西他都要去玩一下。我也跟着踩他填好的坑,在Flutter的路上一去不回。Pub 25個。。可怕。。都是高分做品
flutter_image_editor能夠說是低調爲extended_image量身打造的原生插件,支持旋轉裁剪翻轉,extended_image負責圖片編輯UI,flutter_image_editor提供原生裁剪圖片數據能力。因爲dart image庫在處理圖片的效率問題,原生庫(期待純C++庫)就有了很大的優點(大圖片能夠有10倍速度的提高)。正是由於teamwork才能使flutter上面對於圖片編輯處理最終達到一個完美的狀態。
法法,200,Flutter Candies 🍬 全家桶的樓主。在感覺到大佬們的感化以後,也但願能幫助到更多的Flutter開發者。pub目前13個,屬於項目中比較經常使用的組件。
作項目遇到的第一個遇到的問題就是官方的NestedScrollView,各方求證以及查看源碼以後發現應該只是as design。若是你即將使用官方的NestedScrollView,強力建議先看一下,你一定會遇到下面的問題 掘金文章地址
其實官方對這個是有處理的,是經過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;
},
複製代碼
因爲NestedScrollView內部裏面有一個ScrollController,TabView裏面的列表的ScrollPosition都將會attach到這個sc上面,在滾動其中一個的時候,同步所有的ScrollPositions。因爲篇幅緣由,我這裏直接放以前的文章了。
因爲body裏面的列表必須共用同一個ScrollController,因此你是不能給列表單獨設置ScrollController,這樣會致使內部的outer_scroll_controller和inner_scroll_controller沒法協同工做。
你們想使用ScrollController無非3點。
1.下拉刷新,已提供demo
2.加載更多,已提供demo
3.控制列表滾動,已將屬性暴露出來
import 'package:flutter/widgets.dart' hide NestedScrollView;
複製代碼
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;
},
);
複製代碼
請自行查看issue
extended_image的基礎庫,若是你只須要網絡圖片緩存功能,你能夠只引用這個庫
Image(
image: ExtendedNetworkImageProvider("", cache: true),
);
複製代碼
富有中國特點強大功能的富文本 掘金文章地址
主要功能
爲了快速構建富文本,好比把 '[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});
}
複製代碼
Flutters上面惟一能支持輸入內容是WidgetSpan的輸入框 掘金文章地址
主要功能
仿掘金推特色贊按鈕,帶數量滾動動畫掘金文章地址
能夠在任何滾動場景中使用(包括NestedScrollView)的自定義下拉刷新組件, 只提供了下拉刷新的狀態,你能夠最大化的自定義本身的效果而不用拘泥於組件自己提供。你能夠根據狀態距離,構建出任何你想要的效果。demo裏面的4種效果只是例子,歡迎你們pr更多更有趣的效果。掘金文章地址
這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;
}
}
複製代碼
繼承了UWP的加載更多思想的做品,將UI跟數據源的契約完美打通,你只要寫過一次,你就會愛上這種方式。掘金文章地址
支持TabBarView的聯動,就是說二級TabBarView不能滑動了,就看一級能不能滑動,能滑動就滑動一級的 掘金文章地址
輕巧靈活的路由註解工具,一行命令完成路由映射. 掘金文章地址
使用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,這應該是你必看的網站。
每一個人都從萌新而來,若是你想開森的寫代碼,本身解決問題是必須的
英語是很重要的。
問問題的時候,儘可能上代碼,或者說明你的意圖,由於可能你的想法或者解決方向就是錯誤的
若是實在沒法本身解決,能夠求助於大佬,可是請注意提問方式,畢竟好溝通能節約雙方的時間,大佬也要工做也要吃飯。
把你的想要效果的插件的名字或者其餘平臺的組件叫什麼名字,轉爲爲英文,到pub 上面搜索,分高的使用的人多,相對就比較穩定更好。
咱們常常運行別人組件的時候,發現各類下載失敗,各類下載緩慢 請使用國內鏡像,飛通常的趕腳。
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' }
#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
複製代碼
在開發中,咱們發現給組件設置了大小,可是卻沒有效果。舉個栗子,在Appbar的leading/actions中,咱們想直接設置寬高是不可能的。 咱們須要使用UnconstrainedBox來移除父widget對子大小的限制,以下代碼
AppBar(
title: Text(widget.title),
leading: UnconstrainedBox(
child: Container(
width: 50.0,
height: 10.0,
color: Colors.red,
),
),
),
複製代碼
double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
複製代碼
Column(
children: <Widget>[
///你的佈局
Expanded(
child: Container(),
),
///頂起你的佈局
Container(
height: keyboardHeight,
)
],
);
複製代碼
其實這個我也是在源碼裏面scaffold.dart中看到的,抄做業很重要
關鍵代碼
而且在_ScaffoldLayout中增長了這個高度中國鏡像你在等什麼呢,學起來
issue地址 經過設置下面代碼解決,全局設置文字主題
textTheme: theme.textTheme.copyWith(
subhead: theme.textTheme.subhead
.copyWith(textBaseline: TextBaseline.alphabetic)),
複製代碼
咱們常常聽到的就是爲何個人文本設置了溢出顯示,可是它卻顯示黃色溢出警告了? 對於文本Text來講,若是它的父Widget沒有給它作大小限制,它默認是無限長的 咱們解決的方法以下。
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增長了對material風格的設置,因此不少地方都有一些限制。其實也不能怪官方,這是一種設計規範。可是咱們就是想本身騷怎麼辦呢?? 我以前寫了個 my_app_bar.dart,以前一直放gists上面,不方便你們查看,如今也移入了🍬。這是一個簡單的實現,看明白了代碼原理以後,你能夠擴展出更多適合本身的appbar。
由於有好幾我的問過,因此我寫了個簡單的demo。主要是靠NotificationListener來監聽滾動來控制頭部。
不是每一種警告,都是必定要管的。警告只是官方告訴你須要注意這點,這就是爲何Release下面不會出現警告。警告不等於錯誤。
我這裏舉一個栗子。NestedScrollView的body實際上是SliverFillRemaining包住的,它會跟着一塊兒滾動。可是咱們這裏佈局裏面是一個Tabbar,它是一個有固定高度的組件,當它超出屏幕的時候就會出現警告。可是事實上,這種警告並不能影響咱們的使用。
若是你是由於頁面從新build就影響你的業務,那應該好好檢查下業務邏輯代碼。build的緣由是route變化時候的動畫,以及NavigatorState中Overlay(實際就是Stack),route位置變化而引發的頁面build。
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系列的東東不少,咱們下面來一一介紹一下。
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的使用場景,你能夠完成其餘平臺可能須要很費勁才能作出來的效果。下面舉一些經常使用的栗子吧。
return CustomScrollView(
slivers: <Widget>[
SliverList(),
SliverList(),
],
);
複製代碼
若是你是水平垂直嵌套的話,能夠設置內部那個Listview的高度或者寬度
return ListView(
children: <Widget>[
SizedBox(
height: 60.0,
child: ListView.builder(
itemBuilder: (c, index) {}, scrollDirection: Axis.horizontal),
)
],
);
複製代碼
注意這個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++更好的支持。