本文原作者: 戀貓de小郭,原文發(fā)布于:GSYTech
隨著 Flutter 3.3 正式版發(fā)布,Global Selection 終于有了官方的正式支持,「該功能補(bǔ)全了 Flutter 長時(shí)間存在 Selection 異常等問題,特別是在 Flutter Web 下經(jīng)常會(huì)有選擇文本時(shí)與預(yù)期的行為不匹配的情況」。
使用
「使用 SelectionArea 也十分簡單,如下代碼所示,只需要在您想要支持的地方添加 SelectionArea 即可」,甚至可以在每個(gè)路由下的Scaffold 添加SelectionArea 來全面啟用支持。
默認(rèn)情況下SelectionArea 已經(jīng)實(shí)現(xiàn)了所有常見的功能,并且 Flutter 針對(duì)不同平臺(tái)進(jìn)行了差異化實(shí)現(xiàn),如下圖所示 Android 和 iOS 會(huì)有不同的樣式效果。
所以如果您覺得這個(gè)判斷有問題,完全可以自己 override 一個(gè)自定義的 TextSelectionControls,比如在canSelectAll 直接 return true。
是的,「對(duì)于SelectionArea 我們可以通過繼承 TextSelectionControls 來自定義」:
通過 buildToolbar 自定義彈出的 Toolbar 樣式和邏輯,甚至您可以添加一些額外的標(biāo)簽能力,比如 "插入圖片"; 通過 buildHandle 自定義 Selection Handle 可拖動(dòng)部分的樣式。
而在SelectionArea 里,不管是 Handle 還是 Toolbar,都是通過新增 Overlay 來實(shí)現(xiàn)樣式,這部分的邏輯主要在 SelectionOverlay 對(duì)象:
如果您還不了解Overlay,可以簡單理解為:「默認(rèn)情況下所有的路由頁面都在一個(gè) Overlay 下,打開一個(gè) Route 就是添加一個(gè) OverlayEntry 到 Overlay 里」。
所以 Handle 和 Toolbar 都是通過OverlayEntry 打開的特殊 "路由" 控件,擁有新的層級(jí),例如下方右圖就是 Toolbar 所在的OverlayEntry。
「另外,對(duì)于 Handle 的顏色定義,默認(rèn)情況下主要來自 TextSelectionTheme 和Theme」。
例如MaterialTextSelectionControls 里,start 和 end 兩個(gè) Handle 的顏色,默認(rèn)是通過 TextSelectionTheme 的 selectionHandleColor 或者Theme 的primary 來設(shè)置。
而對(duì)于文字的選中區(qū)塊的顏色,默認(rèn)是通過 DefaultSelectionStyle 的 selectionColor 來顯示,當(dāng)然,如下第二張圖所示,在 MaterialApp 里它依然和 TextSelectionTheme 的 selectionColor 或者Theme 的primary 有關(guān)系。
「那如果您還想要在SelectionArea 下的某些內(nèi)容不允許被選中呢」?
這里 Flutter 提供了 SelectionContainer.disabled 實(shí)現(xiàn),只要在對(duì)應(yīng)內(nèi)容嵌套 SelectionContainer.disabled,那么這部分內(nèi)容下的文本就無法被選中。
為什么嵌套SelectionContainer.disabled 就可以禁用文本選中的能力?這其實(shí)和SelectionArea 的實(shí)現(xiàn)有關(guān)系:
SelectionContainer 內(nèi)部實(shí)現(xiàn)了一個(gè) InheritedWidget,它會(huì)往下共享一個(gè) SelectionRegistrar,而默認(rèn)情況下SelectionArea 內(nèi)部使用了SelectionContainer 并且往下共享了對(duì)應(yīng)的 Registrar 實(shí)現(xiàn)。
SelectionArea 內(nèi)部的 SelectionContainer 是有對(duì)應(yīng)的 registrar 實(shí)現(xiàn)往下共享; SelectionContainer.disabled 內(nèi)部的registrar 是 null。
△圖二
到這里您應(yīng)該大致理解了如何使用和自定義一些 SelectionArea 的能力,那么接下來介紹兩個(gè) "Bug",通過這兩個(gè) "Bug" 我們深入理解SelectionArea 內(nèi)部的實(shí)現(xiàn)情況。
問題 1
如下代碼所示,「當(dāng)使用了WidgetSpan 之后,默認(rèn)情況下,用戶在開始位置拖拽 Handle 進(jìn)行選擇時(shí)會(huì)無法選中WidgetSpan 里的文本」。
PS:其實(shí)拖動(dòng)可以選中,只是這里暫時(shí)以不能選中的情況下作為切入點(diǎn)。
當(dāng)然,「其實(shí)在拖動(dòng)Handle還是可以選中WidgetSpan里的文本,比如您從HelloWorld開始拖動(dòng),這里拖動(dòng)選中不了的原因后面會(huì)解釋」。
問題2
如果當(dāng)我們點(diǎn)擊了全選會(huì)怎么樣?如下圖所示,在我們點(diǎn)擊全選之后,可以看到兩個(gè) "奇怪" 的問題:
WidgetSpan 里的 Hello World 可以被選中了; 左側(cè)的 Start Handle 位置不是在文本開頭,而是在WidgetSpan 開始。
我們首先看第一點(diǎn),「為什么點(diǎn)擊全選時(shí),WidgetSpan 里的 Hello World 可以被選中」?
其實(shí)全選操作和拖拽 Handle 最大的不同就是: 它是往下直接發(fā)出全選事件 SelectAllSelectionEvent,而該事件會(huì)觸發(fā)所有 child 響應(yīng)事件,自然也就包括了 WidgetSpan 里的 Hello World。
_handleSelectAll 獲取得到 _textSelectionStart 和 _textSelectionEnd,表明此時(shí)控件已經(jīng)被選中; didChangeSelection 里通過 paragraph.markNeedsPaint() 觸發(fā)重繪,然后增加選中時(shí)的覆蓋顏色。
首先我們看,為什么復(fù)制出來之后的內(nèi)容會(huì)是Hello World!Flutter isthe best!?
正如前面說到的,復(fù)制調(diào)用的是 getSelectedContent 方法,如下代碼所示,「可以看到在selectables 這個(gè) List 的第一位就是Hello World,所以最終拼接出來的文本會(huì)是Hello World!Flutter isthe best!」 。
目前這個(gè)問題在 master 和 stable 分支均可以復(fù)現(xiàn),對(duì)應(yīng) issue 我也提交在#111021。
最后
雖然SelectionArea 的出現(xiàn)補(bǔ)全了 Flutter 的長久以來的短板之一,不過基于SelectionArea 實(shí)現(xiàn)的復(fù)雜程度,目前SelectionArea 還有不少的細(xì)節(jié)需要優(yōu)化,但是萬事開頭難,本次 3.3 SelectionArea 的落地也算是一個(gè)不錯(cuò)的開始。
最后,相信通過本文大家應(yīng)該對(duì) SelectionArea 的使用和實(shí)現(xiàn)都有了一定的了解。
長按右側(cè)二維碼
查看更多開發(fā)者精彩分享
"開發(fā)者說·DTalk" 面向中國開發(fā)者們征集 Google 移動(dòng)應(yīng)用 (apps & games)?相關(guān)的產(chǎn)品/技術(shù)內(nèi)容。歡迎大家前來分享您對(duì)移動(dòng)應(yīng)用的行業(yè)洞察或見解、移動(dòng)開發(fā)過程中的心得或新發(fā)現(xiàn)、以及應(yīng)用出海的實(shí)戰(zhàn)經(jīng)驗(yàn)總結(jié)和相關(guān)產(chǎn)品的使用反饋等。我們由衷地希望可以給這些出眾的中國開發(fā)者們提供更好展現(xiàn)自己、充分發(fā)揮自己特長的平臺(tái)。我們將通過大家的技術(shù)內(nèi)容著重選出優(yōu)秀案例進(jìn)行谷歌開發(fā)技術(shù)專家 (GDE)的推薦。
?點(diǎn)擊屏末|閱讀原文|即刻報(bào)名參與"開發(fā)者說·DTalk"
原文標(biāo)題:Flutter 3.3 之 SelectionArea 好不好用?用 "Bug" 帶您全面了解它 | 開發(fā)者說·DTalk
文章出處:【微信公眾號(hào):谷歌開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
谷歌
+關(guān)注
關(guān)注
27文章
6169瀏覽量
105437
原文標(biāo)題:Flutter 3.3 之 SelectionArea 好不好用?用 "Bug" 帶您全面了解它 | 開發(fā)者說·DTalk
文章出處:【微信號(hào):Google_Developers,微信公眾號(hào):谷歌開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論