注:亮度調(diào)節(jié)和音量調(diào)節(jié)gif無法體現(xiàn),功能是ok的,其次默認(rèn)Icon鎖的close和open實在難以分辨。
為阜寧等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及阜寧網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站建設(shè)、網(wǎng)站制作、阜寧網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
環(huán)境:Flutter 2.8.1 channel stable ;Dart 2.15.1
需要音頻播放器的看這里: Flutter音樂播放器
重點說下這個工具類,因為視頻播放,涉及到狀態(tài)改變有很多,筆者剛開始選擇使用 InheritedWidget 來在眾多的widget之間共享數(shù)據(jù)。但是總感覺這樣有點繁瑣,且不很優(yōu)雅!
這里非廣告,如果是使用 GetX 就很簡單了,筆者也使用了 GetX 進行封裝了,一瀉千里的趕腳!,但是筆者還是那句話:剛開始接觸Flutter的開發(fā)者不是很建議使用 GetX ,可以先熟悉下Flutter狀態(tài)管理的基礎(chǔ)原理再行使用。而且為了盡量簡潔,還是不引入其他的第三方了。
我們選擇對第三方插件進行封裝的目的不外乎這幾個:
于是筆者就寫了一個工具類 VideoPlayerUtils ,專門且只用來處理播放器的所有業(yè)務(wù)。包括暫停、播放、跳轉(zhuǎn)、調(diào)節(jié)音量、調(diào)節(jié)亮度、切換視頻等操作。在所有的widget中不會引用關(guān)于 video_player 或其他第三方插件的任何信息, VideoPlayerUtils 負(fù)責(zé)widget與播放器之間的所有操作交互。后續(xù)優(yōu)化迭代或更換播放器插件時,只需針對這個工具類進行修改,對所有widget不會有任何的影響,大大的解耦合了。
其中 VideoPlayerState :
提供以上的公共屬性,可以通過 VideoPlayerUtils 來獲取對應(yīng)的值,使用 get 只讀,使外界不會誤修改這些屬性,以保證數(shù)值的安全性。開發(fā)者可根據(jù)自身需要自行添加屬性。
提供以上方法來處理播放器的所有業(yè)務(wù)。同樣的開發(fā)者可根據(jù)自身需要自行添加或修改。
重點說下這個方法,是整個業(yè)務(wù)的核心方法,控制視頻的播放或暫停。開發(fā)者只要遇到播放或暫停是均可調(diào)用此方法,具體是播放或暫停,內(nèi)部根據(jù)傳入的 url 自行判斷,開發(fā)者不需要關(guān)心。
切換新視頻也是使用此方法,傳入的 url 與上次不一致,自動切換新視頻。筆者可根據(jù) statusListener 來監(jiān)聽播放狀態(tài)的改變,以此處理自身邏輯。
這個也需要提下,視頻播放器在播放新視頻時會異步初始化,一般我們的操作是在 initState() 初始化,成功后再 setState() 。這里筆者遇到一個讓人蛋疼的問題:
我們看 video_player 的使用:
VideoPlayer(controller) :widget中已經(jīng)持有了controller。本來筆者封裝的目的就是為了讓widget與controller的之間解耦合。但此時的筆者。。。。
放棄不是不可能放棄的,這輩子都不會放棄的!
于是筆者取了巧,寫了一個初始化監(jiān)聽器 initializedListener ,包換2個參數(shù): bool,Widget ,初始化是否成功;其中widget為初始化成功返回需要展示的播放器UI,失敗默認(rèn)返回 const SizedBox() 。
到這里就可以簡單使用了:
沒看錯,視頻播放就是這么簡單。
如果有更多的業(yè)務(wù)功能,筆者也按照自己的需求寫了一套,同樣的開發(fā)者可根據(jù)自身需要自行添加或修改。
VideoPlayerGestures 主要是處理手勢的,比如快進、快退等跳轉(zhuǎn)播放;左側(cè)上下滑動調(diào)節(jié)亮度;右側(cè)上下滑動調(diào)節(jié)音量;單擊是否開啟沉浸式播放,所有widget的隱藏與顯示;雙擊播放、暫停等。
哦,還有 PercentageWidget 也放到這個文件下了,就是這玩意:
因為顯示的百分比與手勢相關(guān),隨著手勢移動而更新。開發(fā)者可自行處理。
筆者處出于簡單考慮,就按照整個UI的位置命名了。瞅一眼就知道是啥玩意。
同樣的開發(fā)者可根據(jù)自身需要自行添加或修改。
就是這玩意:
同樣的開發(fā)者可根據(jù)自身需要自行添加或修改。話說這個鎖的 Icon 的open和close是真的難分辨!
就是這玩意:
同樣的開發(fā)者可根據(jù)自身需要自行添加或修改。
這玩意是自定義的,別問,問就是跟產(chǎn)品干一架落了下風(fēng)
主要就是自定義這玩意:
同樣的開發(fā)者可根據(jù)自身需要自定義。
注:這里沒有添加緩沖的進度,開發(fā)可查看 video_player 中的源碼 VideoProgressIndicator ,按業(yè)務(wù)自行定義。
這玩意就是整合以上的widget,再考慮下全屏的安全區(qū)域,沒啥東西。開發(fā)者可自行處理!
具體的實現(xiàn)監(jiān)聽器的思路, 看這里 。
自此一個漂亮的Flutter視頻播放器就已經(jīng)結(jié)束了。如果您覺得對您有些許幫助的話,歡迎 Star !
一年半前玩過flutter,忘光光...現(xiàn)在是時候重新拾取了。~
啟動頁一般只放圖片或者加幾行文字。
1、創(chuàng)建好flutter項目之后,在lib文件下面新建launch.dart或xx.dart.
2、在根目錄下新建images文件夾,如已有直接放入圖片
3、flutter_yijiake.iml中加入注入該圖片,并注意空格
4、在根目錄下的test/widget_test.dart中更改默認(rèn)的啟動頁為當(dāng)前的啟動頁路徑
5、最后重新設(shè)置啟動時的頁面
6、非常簡單的啟動頁面放logo圖片
值得一說的是,flutter框架的UI組件需要已new 組件的形式展開。
在玩安卓上有款組件化開源app的項目,一款模仿 Eyepetizer | 開眼視頻的 開源app,這款app設(shè)計風(fēng)格特別喜歡的,比較簡潔,美觀,然后最近又在學(xué)flutter的知識,于是就寫了一款flutter版本的開源短視頻,效果也是聽不錯的,廢話不多說,先上效果圖。
先附上項目地址:
項目api會在后面的參考鏈接里,或者直接項目內(nèi)查看。
項目地址:
更新:6/30 項目新增下拉刷新,上拉加載功能
kotlin版本開眼短視頻開發(fā)中,敬請期待...
總結(jié):在此感謝參考的伙伴的文章,寫的也很好,然后我將這個項目改寫成了flutter,當(dāng)中也學(xué)習(xí)到了很多flutter相關(guān)的知識,后續(xù)還有繼續(xù)鞏固,不斷學(xué)習(xí)。
參考鏈接(包含本項目的api)
在以前的 《Flutter 上默認(rèn)的文本和字體知識點》 和 《帶你深入理解 Flutter 中的字體“冷”知識》 中,已經(jīng)介紹了很多 Flutter 上關(guān)于字體有趣的知識點,而本篇講繼續(xù)介紹 Flutter 上關(guān)于 Text 的一個屬性: FontFeature , 事實上相較于 Flutter ,本篇內(nèi)容可能和前端或者設(shè)計關(guān)系更密切 。
什么是 FontFeature ? 簡單來說就是影響字體形狀的一個屬性 ,在前端的對應(yīng)領(lǐng)域里應(yīng)該是 font-feature-settings ,它有別于 FontFamily ,是用于指定字體內(nèi)字的形狀的一個參數(shù)。
我們知道 Flutter 默認(rèn)在 Android 上使用的是 Roboto 字體,而在 iOS 上使用的是 SF 字體,但是其實 Roboto 字體也是分很多類型的,比如你去查閱手機的 system/fonts 目錄,就會發(fā)現(xiàn)很多帶有 Roboto 字樣的字體庫存在。
所以 Roboto 之類的字體庫是一個很大的字體集,不同的 font-weight 其實對應(yīng)著不同的 ttf ,例如默認(rèn)情況下的 Roboto 是不支持 font-weight 為 600 的配置 :
所以如下圖所示,如果我們設(shè)置了 w400 - w700 的 weight ,可以很明顯看到中間的 500 和 600 其實是一樣的粗細,所以在 設(shè)置 weight 或者設(shè)計 UI 時,就需要考慮不同平臺上的 weight 是否支持想要的效果 。
回歸到 FontFeature 上,那 Roboto 自己默認(rèn)支持多少種 features 呢? 答案是 26 種,它們的編碼如下所示,運行后效果也如下圖所示,從日常使用上看,這 26 種 Feature 基本滿足開發(fā)的大部分需求。
而 iOS 上的 SF pro 默認(rèn)支持 39 種 Features , 它們的編碼如下所示,運行后效果也如下圖所示,可以看到 SF pro 支持的 Features 更多。
所以可以看到,并不是所有字體支持的 Features 都是一樣的,比如 iOS 上支持 sups 上標(biāo)顯示和 subs 下標(biāo)顯示,但是 Android 上的 Roboto 并不支持,甚至很多第三方字體其實并不支持 Features 。
有趣的是,在 Flutter Web 有一個渲染文本時會變模糊的問題 #58159 ,這個問題目前官方還沒有修復(fù),但是你可以通過給 Text 設(shè)置任意 FontFeatures 來解決這個問題。
最后,如果對 FontFeature 還感興趣的朋友,可以通過一下資料深入了解,如果你還有什么關(guān)于字體上的問題,歡迎留言討論。
基于網(wǎng)友的問題再補充一下拓展知識,畢竟這方面內(nèi)容也不多 。
事實上在 dart 里就可以看到對應(yīng) FontWeight 約定俗稱用的是字體集里的什么字體:
所以如果對于默認(rèn)字體有疑問,可以在你的手機字體找找是否有對應(yīng)的字體, 比如雖然我們說 roboto 沒有 600 ,但是如果是 roboto mono 字體集是有 600 的 fontweight ,甚至還有 600 斜體: 。
另外注意這是 Flutter 而不是原生,具體實現(xiàn)調(diào)用是在 Engine 的 paragraph_skia.cc 和 paragraph_builder_skia.cc 下對應(yīng)的 setFontFamilies 相關(guān)邏輯,當(dāng)然默認(rèn)字體庫指定在 typography.dart 下就看到,例如 'Roboto' 、 '.SF UI Display' 、 '.SF UI Text' 、 '.AppleSystemUIFont' 、 'Segoe UI' :
另外如果你在 Mac 的 Web 上使用 Flutter Web,可以看到指定的是 .AppleSystemUIFont ,而對于 .AppleSystemUIFont 它其實不算是一種字體,而是蘋果上字體的一種集合別稱:
[圖片上傳失敗...(image-40f5ce-1648368234737)]
還有,如果你去看 Flutter 默認(rèn)自帶的 cupertino/context_menu_action.dart ,就可以看到一個有趣的情況:
當(dāng)然,前面我們說了那么多,主要是針對英文的情況下,而在中文下還是有差異的 ,之前的文章也介紹過:
例如,在蘋果上的簡體中文其實會是 PingFang SC 字體,對應(yīng)還有 PingFang TC 和 PingFang HK 的繁體集,而關(guān)于這個問題在 Flutter 上之前還出現(xiàn)過比較有意思的 bug :
當(dāng)然后續(xù)的 #16709 修復(fù)了這個問題 ,而在以前的文章我也講過,當(dāng)時我遇到了 “Flutter 在 iOS 系統(tǒng)上,系統(tǒng)語言是韓文時,在和中文一起出現(xiàn)會導(dǎo)致字體顯示異常" 的問題 :
解決方法也很簡單,就是給 fontFamilyFallback 配置上 ["PingFang SC" , "Heiti SC"] 就可以了,這是因為韓文在蘋果手機上使用的應(yīng)該是 Apple SD Gothic Neo 這樣的超集字體庫,【廣】這個字符在這個字體集上是不存在的,所以就變成了中文的【廣】;
所以可以看到,字體相關(guān)是一個平時很少會深入接觸的東西,但是一旦涉及多語言和繪制,就很容易碰到問題的領(lǐng)域 。