記錄下自己踩過(guò)的坑,怕忘了
成都做網(wǎng)站、成都網(wǎng)站建設(shè)的開發(fā),更需要了解用戶,從用戶角度來(lái)建設(shè)網(wǎng)站,獲得較好的用戶體驗(yàn)。創(chuàng)新互聯(lián)多年互聯(lián)網(wǎng)經(jīng)驗(yàn),見的多,溝通容易、能幫助客戶提出的運(yùn)營(yíng)建議。作為成都一家網(wǎng)絡(luò)公司,打造的就是網(wǎng)站建設(shè)產(chǎn)品直銷的概念。選擇創(chuàng)新互聯(lián),不只是建站,我們把建站作為產(chǎn)品,不斷的更新、完善,讓每位來(lái)訪用戶感受到浩方產(chǎn)品的價(jià)值服務(wù)。
一.TextField:
1.去掉輸入數(shù)字的計(jì)數(shù):decoration中的counterStyle: TextStyle(color: Colors.transparent).
2.去掉獲取和失去焦點(diǎn)時(shí)邊框改變顏色的效果:decoration內(nèi)border: InputBorder.none,
3.去邊框時(shí)設(shè)置BorderSide的width為0或color: Colors.transparent后依然存在邊框時(shí),需要設(shè)置為borderSide: BorderSide.none
4.設(shè)置背景色需要在decoration內(nèi) ? ? filled:true, ? fillColor: Colors.blue同時(shí)設(shè)置才會(huì)顯示
二.Uint8List類型和string類型,Listint的轉(zhuǎn)換
連續(xù)兩次base64解碼時(shí),參數(shù)只能使用string類型,但是base64解碼后是Uint8List類型,此時(shí)需要將Uint8List類型轉(zhuǎn)換為string類型,使用:utf8.decode(Uint8List)即可,需要import 'dart:convert';
Listint轉(zhuǎn)Uint8List:讀取接口時(shí)獲取的數(shù)據(jù)是Listint的圖片數(shù)據(jù),想顯示時(shí)需要轉(zhuǎn)成Uint8List,然后使用Image.memory(),使用:Uint8List.fromList(Listint)即可
三.報(bào)錯(cuò):DioError [DioErrorType.DEFAULT]: FormatException: Unexpected character (at character 1)MGFlMFo0NEZ3RWNMbE5YbGNGOXZGcUlJdUhIS2x2Q3NlckxqWXlEeG5JWndZdXIrSUpLN3ZOczR...
這是因?yàn)閐io請(qǐng)求返回的數(shù)據(jù)默認(rèn)是以json的格式讀取的,而返回的數(shù)據(jù)是密文形式,需要修改dio的Options的responseType為ResponseType.PLAIN,這樣返回的數(shù)據(jù)就以字符串形式處理.
四.去掉點(diǎn)擊控件背景出現(xiàn)的水波紋效果,即去掉md的效果:
在main.dart的MaterialApp內(nèi)的theme加上splashColor: Colors.transparent
五.布局去掉沉浸式效果和布局設(shè)置占滿全屏卻無(wú)效的問(wèn)題
使用Scaffold的body的布局默認(rèn)是沉浸式的,將狀態(tài)欄一起包含了,可以通過(guò)在body后添加一層SafeArea即可.
布局設(shè)置double.infinity占滿全屏高度卻無(wú)效,大部分情況都是因?yàn)槟骋患?jí)的父布局的高度已經(jīng)有了限制,所以設(shè)置充滿屏幕只會(huì)充滿父布局,有些widget默認(rèn)是按內(nèi)容填充類似wrap_content就會(huì)導(dǎo)致寫布局的過(guò)程中自己沒有限制高度但最后的布局不是自己想要的,可以給各個(gè)父布局設(shè)置不同背景顏色來(lái)查看是從哪兒開始被限制了高度來(lái)排查問(wèn)題.
六.占滿剩余空間,類似android的match_parent可以使用double.infinity
七.LinearProgressIndicator
1.LinearProgressIndicator設(shè)置進(jìn)度值的顏色為單一顏色:valueColor : new AlwaysStoppedAnimation(Color(JColor.blue))
2.給LinearProgressIndicator設(shè)置圓角:ClipRRect(
borderRadius:BorderRadius.circular(60.0),
child:LinearProgressIndicator(value:0.2,backgroundColor:Color(JColor.grayBg),valueColor:new AlwaysStoppedAnimation(Color(JColor.blue)),
)
八.Expanded:
1.若嵌套多層column且內(nèi)容的高度都不確定需要占滿剩余空間,需要每層的column的內(nèi)容都嵌套一層expanded來(lái)申明每層都占滿剩余的空間,否則最里面的內(nèi)容層需要指定高度,不然會(huì)報(bào)錯(cuò)
九.Container設(shè)置最小/大寬度或高度:
constraints:BoxConstraints(minHeight:56),
十.滑動(dòng)的widget嵌套:
1.解決滑動(dòng)沖突:內(nèi)層嵌套的滑動(dòng)widget設(shè)置physics:NeverScrollableScrollPhysics()
2.解決滑動(dòng)嵌套u(yù)i顯示不出來(lái)或者報(bào)錯(cuò),內(nèi)層的滑動(dòng)widget設(shè)置shrinkWrap:true
十一.使用multi_image_picker: ^4.3.4安卓運(yùn)行報(bào)錯(cuò)Didn't find class "com.sangcomz.fishbun.FishBunFileProvider"
1.需要android工程支持androidx,需要在android工程的gradle.properties內(nèi)添加android.enableJetifier=true和android.useAndroidX=true并點(diǎn)擊右上角的open for editing in android studio,運(yùn)行成功后就可以了
十二.使用textfield時(shí)的文字ui總是很高
使用了maxlength且只是在textfield的InputDecoration設(shè)置counterStyle的顏色為透明使下面的計(jì)數(shù)文字消失會(huì)導(dǎo)致文字ui很高,counter的計(jì)數(shù)文字只是顏色是透明但依然在布局中占了位置所以導(dǎo)致文字很高,直接使用counterText:""即可
十三.使用ListView報(bào)錯(cuò)Vertical viewport was given unbounded height
需要將ListView放入Expanded內(nèi)部
做 Android 的朋友都知道,在 Android 中,限定子元素大小的方法有三種,分別是 match_parent 、 wrap_content 、 fixed size 。如果使用 ConstraintLayout,還會(huì)有 match_constraint 。
這些值被設(shè)置到子元素的 layout_width 和 layout_height,由父元素解析生成 LayoutParams 設(shè)置給子元素,并在父元素的 measure 過(guò)程中使用它們以及父元素得到的 measureSpec 來(lái)確定子元素的大小。雖然子元素的大小最終由父元素決定,但父元素幾乎不會(huì)違背子元素對(duì)自身大小的期望。因此你可以認(rèn)為在 Android 中子元素的大小可以由子元素自己決定 。子元素想要什么大小,給自身的 layout_width 和 layout_height 指定不同的值即可。
而在 Flutter 中,就完全不一樣了。Flutter 積極組合的設(shè)計(jì),希望一切布局都盡量通過(guò)組合的方式來(lái)實(shí)現(xiàn)。組合優(yōu)于繼承這是真理,但 Flutter 卻走向了極端。連指定子元素的大小、padding、margin、translate、background 等等都需要通過(guò)嵌套來(lái)實(shí)現(xiàn),這就是導(dǎo)致嵌套地獄的根源。
以指定子元素的大小為例,你需要給子元素套一層 SizedBox,通過(guò)它來(lái)限定子元素的大小?;诖耍憧梢岳斫鉃樵谝话闱闆r下, Flutter 中子元素的大小無(wú)法由子元素自己決定,始終由其父元素決定 ,這和 Android 有本質(zhì)的區(qū)別。
Flutter 也沒有提供 match_parent 來(lái)讓子元素?fù)螡M父元素, wrap_content 來(lái)讓子元素內(nèi)容有多大就撐多大。但是它提供了 double.infinity。我們一般使用它來(lái)讓子元素?fù)螡M父元素。但其實(shí) double.infinity 也用來(lái)表示 wrap_content 。這得從 Flutter 的布局過(guò)程說(shuō)起。
Flutter 的布局過(guò)程總結(jié)起來(lái)就三句話:
這里有一個(gè)很重要的點(diǎn)是, 子元素的大小永遠(yuǎn)不能違背父元素的約束 ,否則就會(huì)拋異常。子元素為自身的 size 賦值時(shí),會(huì)觸發(fā)以下檢測(cè):
為了避免這個(gè)異常,子元素在設(shè)置自身 size 之前,會(huì)先嘗試滿足父元素的約束:
這樣就能保證設(shè)置的 size 永遠(yuǎn)滿足父元素的約束,不引發(fā)異常。
當(dāng)你使用 double.infinity 嘗試撐滿父元素時(shí),這里的 contentWidth 值為 double.infinity,但 constraints.constrainWidth 會(huì)返回父元素的寬度,這就起到了 match_parent 的作用。這里的隱含意思是子元素的大小不可能真的為無(wú)限大,因?yàn)闆]有任何一個(gè) UI 框架能渲染無(wú)限大的東西,因?yàn)槟且馕吨鵁o(wú)限大的資源消耗。
wrap_content 又是咋回事呢?其實(shí)也是同樣的道理。
當(dāng)父元素對(duì)子元素沒有大小要求時(shí),會(huì)向子元素傳遞寬松約束,即只限制最大的大小,一般為父元素的大小。意思是子元素想要多大就給多大,但不能超過(guò)自身大小。但有些 Widget 就沒有這個(gè)限制,它們?cè)试S子元素的大小超過(guò)自己的大小,因此它們給子元素傳遞的最大大小為 double.infinity。但子元素測(cè)量自己時(shí),發(fā)現(xiàn)父元素給的最大大小為 double.infinity,不可能真的將自身大小設(shè)置為 double.infinity,因?yàn)? Flutter 沒法渲染無(wú)限大的東西。如果你嘗試著這么做,同樣會(huì)拋異常。所以一般情況下,子元素會(huì)直接將 double.infinity 當(dāng)作 wrap_content 處理,向父元素反饋?zhàn)约旱膬?nèi)容大小。
所以總結(jié)下來(lái)就是:
當(dāng)然一切的原因都在于 Flutter 設(shè)計(jì)之初沒有考慮像 Android 那樣用 -1 來(lái)表示 match_parent ,-2 來(lái)表示 wrap_content 。如果這么做的話,就沒有 double.infinity 什么事了。
多數(shù)時(shí)候你都可以使用 double.infinity 來(lái)達(dá)到 match_parent 的效果,但也不總是這樣。你永遠(yuǎn)如法用它來(lái)自下而上的達(dá)到 wrap_content 的效果。因?yàn)樗荒茏陨隙隆U嫦胱屪釉刈陨泶笮? wrap_content ,那就結(jié)合支持 wrap_content 的 Widget 比如 Center 使用吧。或者使用 Flutter ConstraintLayout 。它自帶了 matchParent 、 wrapContent 、 fixedSize 、 matchConstraint 的支持。
1.使用sizebox保持間距
2.使用Spacer填充盡可能大的空間
Row(
children: Widget[
Text("1"),
Spacer(), // use Spacer
Text("2"),
],
)
3.使用mainAxisAlignment對(duì)齊方式控制彼此間距
4.如果不用行的話,還可以使用Wrap并指定spacing
5)同樣是使用Wrap,設(shè)置spaceAround
Wrap(
alignment: WrapAlignment.spaceAround, // 空白包圍住元素
children: Widget[
Text("1"),
Text("2"),
],
)
該方案來(lái)自于 這位博主請(qǐng)點(diǎn)擊查看
[img]流式布局(Liquid)的特點(diǎn)(也叫"Fluid") 是頁(yè)面元素的寬度按照屏幕分辨率進(jìn)行適配調(diào)整,但整體布局不變。柵欄系統(tǒng)(網(wǎng)格系統(tǒng)),用戶標(biāo)簽等。在Flutter中主要有Wrap和Flow兩種Widget實(shí)現(xiàn)。
在介紹Row和Colum時(shí),如果子widget超出屏幕范圍,則會(huì)報(bào)溢出錯(cuò)誤,在Flutter中通過(guò)Wrap和Flow來(lái)支持流式布局,溢出部分則會(huì)自動(dòng)折行。
上述有很多屬性和Row的相同,其意義其實(shí)也是相同的,這里我就不一一介紹了,主要介紹下不同的屬性:
我們一般很少會(huì)使用Flow,因?yàn)槠溥^(guò)于復(fù)雜,需要自己實(shí)現(xiàn)子widget的位置轉(zhuǎn)換,在很多場(chǎng)景下首先要考慮的是Wrap是否滿足需求。Flow主要用于一些需要自定義布局策略或性能要求較高(如動(dòng)畫中)的場(chǎng)景。Flow有如下優(yōu)點(diǎn):
我們對(duì)六個(gè)色塊進(jìn)行自定義流式布局:
實(shí)現(xiàn)TestFlowDelegate:
可以看到我們主要的任務(wù)就是實(shí)現(xiàn)paintChildren,它的主要任務(wù)是確定每個(gè)子widget位置。由于Flow不能自適應(yīng)子widget的大小,我們通過(guò)在getSize返回一個(gè)固定大小來(lái)指定Flow的大小,實(shí)現(xiàn)起來(lái)還是比較麻煩的。