bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

flutter頂層頁,flutter 蒙層

Flutter 啟動頁的前世今生適配歷程

APP 啟動頁在國內是最常見也是必備的場景,其中啟動頁在 iOS 上算是強制性的要求,其實配置啟動頁挺簡單,因為在 Flutter 里現在只需要:

創新互聯建站主要從事網站設計制作、成都網站設計、網頁設計、企業做網站、公司建網站等業務。立足成都服務陸川,十余年網站建設經驗,價格優惠、服務專業,歡迎來電咨詢建站服務:13518219792

一般只要配置無誤并且圖片尺寸匹配,基本上就不會有什么問題, 那既然這樣,還有什么需要適配的呢?

事實上大部分時候 iOS 是不會有什么問題, 因為 LaunchScreen.storyboard 的流程本就是 iOS 官方用來做應用啟動的過渡;而對于 Andorid 而言,直到 12 之前 windowBackground 這種其實只能算“民間”野路子 ,所以對于 Andorid 來說,這其中就涉及到一個點:

所以下面主要介紹 Flutter 在 Android 上為了這個啟動圖做了哪些騷操作~

在已經忘記版本的“遠古時期” , FlutterActivity 還在 io.flutter.app.FlutterActivity 路徑下的時候,那時啟動頁的邏輯相對簡單,主要是通過 App 的 AndroidManifest 文件里是否配置了 SplashScreenUntilFirstFrame 來進行判斷。

在 FlutterActivity 內部 FlutterView 被創建的時候,會通過讀取 meta-data 來判斷是否需要使用 createLaunchView 邏輯 :

是不是很簡單,那就會有人疑問為什么要這樣做?我直接配置 Activity 的 android:windowBackground 不就完成了嗎?

這就是上面提到的時間差問題, 因為啟動頁到 Flutter 渲染完第一幀畫面中間,會出現概率出現黑屏的情況,所以才需要這個行為來實現過渡 。

經歷了“遠古時代”之后, FlutterActivity 來到了 io.flutter.embedding.android.FlutterActivity , 在到 2.5 版本發布之前,Flutter 又針對這個啟動過程做了不少調整和優化,其中主要就是 SplashScreen 。

自從開始進入 embedding 階段后, FlutterActivity 主要用于實現了一個叫 Host 的 interface ,其中和我們有關系的就是 provideSplashScreen 。

默認情況下它會從 AndroidManifest 文件里是否配置了 SplashScreenDrawable 來進行判斷 。

默認情況下當 AndroidManifest 文件里配置了 SplashScreenDrawable ,那么這個 Drawable 就會在 FlutterActivity 創建 FlutterView 時被構建成 DrawableSplashScreen 。

DrawableSplashScreen 其實就是一個實現了 io.flutter.embedding.android.SplashScreen 接口的類,它的作用就是:

之后 FlutterActivity 內會創建出 FlutterSplashView ,它是個 FrameLayout。

FlutterSplashView 將 FlutterView 和 ImageView 添加到一起, 然后通過 transitionToFlutter 的方法來執行動畫,最后動畫結束時通過 onTransitionComplete 移除 splashScreenView 。

所以整體邏輯就是:

當然這里也是分狀態:

當然這個階段的 FlutterActivity 也可以通過 override provideSplashScreen 方法來自定義 SplashScreen 。

看到沒有,做了這么多其實也就是為了彌補啟動頁和 Flutter 渲染之間, 另外還有一個優化,叫 NormalTheme 。

通過該配置 NormalTheme ,在 Activity 啟動時,就會首先執行 switchLaunchThemeForNormalTheme(); 方法將主題從 LaunchTheme 切換到 NormalTheme 。

大概配置完就是如下樣子, 前面分析那么多其實就是為了告訴你,如果出現問題了,你可以從哪個地方去找到對應的點 。

講了那么多, Flutter 2.5 之后 provideSplashScreen 和 io.flutter.embedding.android.SplashScreenDrawable 就被棄用了,驚不喜驚喜,意不意外,開不開心 ?

通過源碼你會發現,當你設置了 splashScreen 的時候,會看到一個 log 警告:

為什么會棄用?

其實這個提議是在 這個 issue 上,然后通過 這個 pr 完成調整。

大概意思就是: 原本的設計搞復雜了,用 OnPreDrawListener 更精準,而且不需要為了后面 Andorid12 的啟動支持做其他兼容,只需要給 FlutterActivity 等類增加接口開關即可 。

也就是2.5之后 Flutter 使用 ViewTreeObserver.OnPreDrawListener 來實現延遲直到加載出 Flutter 的第一幀。

為什么說默認情況? 因為這個行為在 FlutterActivity 里,是在 getRenderMode() == RenderMode.surface 才會被調用,而 RenderMode 又和 BackgroundMode 有關心 。

所以在 2.5 版本后, FlutterActivity 內部創建完 FlutterView 后就會執行一個 delayFirstAndroidViewDraw 的操作。

這里主要注意一個參數: isFlutterUiDisplayed 。

當 Flutter 被完成展示的時候, isFlutterUiDisplayed 就會被設置為 true。

所以當 Flutter 沒有執行完成之前, FlutterView 的 onPreDraw 就會一直返回 false ,這也是 Flutter 2.5 開始之后適配啟動頁的新調整。

看了這么多,大概可以看到其實開源項目的推進并不是一帆風順的,沒有什么是一開始就是最優解,而是經過多方嘗試和交流,才有了現在的版本,事實上開源項目里,類似這樣的經歷數不勝數:

flutter 完全使用GetX 主題切換 以及 自創建Widget的顏色隨主題變化方案

這篇將會解決手動切換主題以及跟隨手機切換主題來更新UI(包括自己創建的Widget)

主題切換有個問題,就是如果是我們自定義或者在 build() 自己創建的部件是不會隨著系統的主題切換而發生主題色變化的(實際測試中,如果頁面在頂層(沒有被push)切換主題并不會觸發 build() 方法,(push之后的頁面切換系統主題是可以觸發 build() 的,而且會頻繁觸發好多次...),既然無法通過重新 build 更新組件的主題色,那么我們在切換主題后,強制觸發整個app的 build() 就可以了)

Flutter組件(Widget)的局部刷新方式

Flutter中有兩個常用的狀態Widget分為StatefulWidget和StatelessWidget,分別為動態視圖和靜態視圖,視圖的更新需要調用StatefulWidget的setState方法,這會遍歷調用子Widget的build方法。如果一個頁面內容比較復雜時,會包含多個widget,如果直接調用setState,會遍歷所有子Widget的build,這樣會造成很多不必要的開銷,所以非常有必要了解Flutter中局部刷新的方式:

globalkey唯一定義了某個element,它使你能夠訪問與element相關聯的其他對象,例如buildContext、state等。應用場景:跨widget訪問狀態。

例如:可以通過key.currentState拿到它的狀態對象,然后就可以調用其中的onPressed方法。

Flutter框架內部提供了一個非常小巧精致的組件,專門用于局部組件的刷新。適用于值改動的刷新。

實現原理:在 initState 中對傳入的可監聽對象進行監聽,執行 _valueChanged 方法,_valueChanged 中進行了 setState 來觸發當前狀態的刷新。觸發 build 方法,從而觸發 widget.builder 回調,這樣就實現了局部刷新。可以看到這里回調的 child 是組件傳入的 child,所以直接使用,這就是對 child 的優化的根源。

可以看到 ValueListenableBuilder 實現局部刷新的本質,也是進行組件的抽離,讓組件狀態的改變框定在狀態內部,并通過 builder 回調控制局部刷新,暴露給用戶使用。

通過這個可以創建一個支持局部刷新的widget樹,比如你可以在StatelessWidget里面刷新某個布局,但是不需要改變成StatefulWidget;也可以在StatefulWidget中使用做部分刷新而不需要刷新整個頁面,這個刷新是不會調用Widget build(BuildContext context)刷新整個布局樹的。

異步UI更新:

很多時候我們會依賴一些異步數據來動態更新UI,比如在打開一個頁面時我們需要先從互聯網上獲取數據,在獲取數據的過程中顯示一個加載框,等獲取到數據時我們再渲染頁面;又比如我們想展示Stream(比如文件流、互聯網數據接收流)的進度。當然StatefulWidget我們完全可以實現以上功能。但由于在實際開發中依賴異步數據更新UI的這種場景非常常見,并且當StatefulWidget中控件樹較大時,更新一個屬性導致整個樹重建,消耗性能,因此Flutter專門提供了FutureBuilder和SteamBuilder兩個組件來快速實現這種功能。

通常情況下,子Widget無法單獨感知父Widget的變化,當父state變化時,通過其build重建所有子widget;

InheriteddWidget可以避免這種全局創建,實現局部子Widget更新。InheritedWidget提供了一種在Widget樹中從上到下傳遞、共享數據的方式。Flutter SDK正是通過InheritedWidget來共享應用主題和Locale等信息。

InheritedWidgetData

TestData

InheritedTest1Page

provider是Google I/O 2019大會上宣布的現在官方推薦的管理方式,而ChangeNotifierProvider可以說是Provider的一種:

yaml文件需要引入provider: ^3.1.0

頂層嵌套ChangeNotifierProvider

創建共享數據類DataInfo:

數據類需要with ChangeNotifier 以使用 notifyListeners()函數通知監聽者更新界面。

使用Provider.of(context)獲取DataInfo

nextPage:

使用Consumer包住需要使用共享數據的Widget

RepaintBoundary就是重繪邊界,用于重繪時獨立于父視圖。頁面需要更新的頁面結構可以用 RepaintBoundary組件嵌套,flutter 會將包含的組件獨立出一層"畫布",去繪制。官方很多組件 外層也包了層 RepaintBoundary 標簽。如果你的自定義view比較復雜,應該盡可能的避免重繪。

以上總結了幾種Flutter的局部刷新的方式,可根據實際需要使用不同的方式,最適合的才是最好的。

(1)Flutter記錄之啟動頁

一年半前玩過flutter,忘光光...現在是時候重新拾取了。~

啟動頁一般只放圖片或者加幾行文字。

1、創建好flutter項目之后,在lib文件下面新建launch.dart或xx.dart.

2、在根目錄下新建images文件夾,如已有直接放入圖片

3、flutter_yijiake.iml中加入注入該圖片,并注意空格

4、在根目錄下的test/widget_test.dart中更改默認的啟動頁為當前的啟動頁路徑

5、最后重新設置啟動時的頁面

6、非常簡單的啟動頁面放logo圖片

值得一說的是,flutter框架的UI組件需要已new 組件的形式展開。

Flutter中showDialog()后關閉Dialog

在耗時操作的時候,一般都要彈出一個加載框,然后在完成的時候再把加載框關掉,在Flutter中可以直接用showDialog()來彈出一個對話框。

這是一個簡單的提示對話框,包含了關閉按鈕,點擊就能關閉。但一般的耗時操作完成,就需要我們自己把dialog關閉掉。

首先,開啟dialog的時機。由于我們需要獲取到BuildContext,所以就得等build()方法走完,這里可以用Future.delayed()來等創建好BuildContext再進行創建,或者用Timer來延遲操作,我選擇了前者。

其中delayed()在initState()結尾來做就行,這里參考網友封裝了一個LoadingDialog。

那么接下來要在什么時機關閉呢?

一開始,我理所當然的以為,是在異步方法結束后,去更新界面的時候關閉,也就是setState(() {})的時候,可是不管怎么嘗試,用Navigator.pop()不行,用Navigator.of(context, rootNavigator: true).pop(result)也不行,用FlutterBoost.singleton.close(id)也不行,用FlutterBoost.singleton.closeCurrent()也不行,都會直接把非Dialog的頁面也關閉掉,這讓我百思不得其解,因為showDialog()的本質也是新建了一個Route出來,也就是最頂層的頁面是彈出的Dialog,可是為什么關不掉呢。

一番思前想后,把showDialog的邏輯移到和異步邏輯同級,也就是setState(() {})外面,然后把showDialog()自身創建的BuildContext傳進去就能正常關閉了。也就是,在setState(() {})的時候,其實用的context還是非Dialog頁面的,所以關閉的當然就不是Dialog了。

持有Dialog自己的BuildContext,然后在異步以后調用就行了。

Flutter開發--如何布局?

相對于iOS開發,Flutter的布局更具有靈活性,每個頁面設計都不一樣,相同頁面可選擇的布局方式也不一樣,如果單純的說應該如何去布局,我覺得不現實,大家可以參考下 Flutter官方的布局教程 。接下來,筆者,通過項目中的一個頁面,來一步一步的拆解布局的流程。整個過程,基本上按照拆解、組件封裝、具體布局這三步來的。

根據設計圖,可以看出整體可以分成兩部分,上面一部分是系統介紹模塊,下面一部分是真正的登錄內容,因為涉及到疊加,因此考慮用Stack;

系統介紹模塊部分:整體也是涉及到疊加,考慮用Stack,分為四部分。最底部漸變色背景用一個contanier,無須指定位置,全視圖擴展;載放logo圖標在上一層,用Image。最后兩個Text同級放在最上層。Image,Text各用Positioned包裹去指定位置。

登錄內容模塊是最外層是一個Contanier容器,去控制背景色和圓角。然后是一個Column元素,逐行排列。

第一行為Image,

第二行為Text,

第三行可以看成一個小Column,分兩塊進行布局

第四行可以看成一個小Column,分兩塊進行布局

第五行可以看作一個TextButton,

第六行可以看作一個Row,分三塊進行布局

通過上面這樣一步一步的分析后,基本上對大致的布局有了一個了解,最外層的控件大致選對(只要能實現的話,就是復雜度以及效率的問題),然后一步一步的拆解每一行的元素,如果有重復的或者覺得可以封裝出來的部分,則進行下一步。

每一行的拆解,大致也是按照這個思路來進行,因此筆者在這里就不做講解了。

在做到第三第四行的時候,發現這兩個很相似,而且設計到一些交互邏輯,筆者就想對第三第四行的這種展示進行封裝,覺得今后的布局可能會用到,因此在這一步,可以先把這一塊兒抽離出一個控件。利用TextField來實現這種輸入操作,具體的實現筆者不再詳細的描述了。

經過這一步,整體的規劃設計圖已經有了,各個組件也都有了,接下來的工作就是組裝了。

具體布局設計到一些細節的地方,例如整體Column的居中對齊(crossAxisAlignment)、間隔(Padding或Container包裹,筆者更喜歡用SizedBox占位)、居左居右居中(Align)、點擊事件(GestureDetector)以及圓角(BorderRadius)等一些特殊情況。

像第六行row是放在底部的,就可以在第六行前面增加一個Spacer()去填充空白區域。

對文字顏色大小等,可以用TextStyle直接設置。

對于輸入框的刪除按鈕,可以用Offstage這種Flutter特有的控制顯示隱藏的控件。

網站題目:flutter頂層頁,flutter 蒙層
網站路徑:http://vcdvsql.cn/article28/dsiipjp.html

成都網站建設公司_創新互聯,為您提供網站導航網站排名網站改版微信公眾號品牌網站建設云服務器

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

外貿網站建設