Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 夜夜草天天干,免费国产成人高清在线电影,亚洲美女黄色片

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          一個易遷移、兼容性高的 Flutter 富文本方案

          一個易遷移、兼容性高的 Flutter 富文本方案

          在閑魚消息體系中,富文本在 UI 側(cè)占了非常大的比重。最近消息部分在整體 Flutter 化,如何解決 Flutter 側(cè)富文本問題,成為了項目早期的風(fēng)險點。

          在 Native 中,消息使用了 HTML 協(xié)議來承載富文本的解析與展示,由于消息的歷史數(shù)據(jù)有落庫的特性,我們必須在 Flutter 側(cè)兼容這種協(xié)議。對于 Flutter,我們是否可以在兼容的基礎(chǔ)上,進(jìn)行能力的擴(kuò)充與完善?

          當(dāng)前閑魚也在升級 Flutter 1.12,所以我們不光要在當(dāng)前版本支持圖文混排,也需要快速遷移到高版本的系統(tǒng)方案。因此我們需要找到一個兼容性高、易遷移的富文本方案。

          行業(yè)現(xiàn)狀

          行業(yè)內(nèi),對于舊版的 RichText (Flutter 1.7.3 之前)已有了解決方案,詳見玄川:《如何低成本實現(xiàn)Flutter 富文本,看這一篇就夠了!》。但這里并沒有對富文本的整個鏈路的解決思路,且 Flutter 自身的 RichText 也在隨著版本迭代進(jìn)行演進(jìn),我們需要一套完整的演進(jìn)方案。

          事實上,F(xiàn)lutter 1.7.3 開始的 RichText 解決了我們的很多麻煩,它是怎么實現(xiàn)的呢?和舊版的實現(xiàn)有什么區(qū)別呢?帶著問題,我們先來分析它的實現(xiàn)原理。

          RichText圖文混排原理

          Flutter 1.7.3 開始,RichText 不再繼承自 LeafRenderObjectWidget,而是繼承自 MultiChildRenderObjectWidget,從這就很容易看出,RichText 將是一個布局控件,內(nèi)部可以有多個子控件。

          創(chuàng)建過程


          如上圖,我們傳給 RichText 的 text 參數(shù)為 InlineSpan,TextSpan、WidgetSpan都是其子類。

          1. RichText 初始化過程中會將 text 中的所有 WidgetSpan 遞歸篩選出來,傳遞給父類 MultiChildRenderObjectWidget。

          2. 創(chuàng)建 MultiChildRenderObjectElement,接著 RichText 會通過 createRenderObject,生成 RenderParagraph。

          3. RenderParagraph 初始化過程中會創(chuàng)建 TextPainter,這個是繪制的核心,這里將會進(jìn)行 layout、paint 和事件分發(fā)操作;然后遞歸篩選 PlaceholderSpan (其實還是 WidgetSpan)。

          渲染過程


          上圖為 RenderParagraph 內(nèi)的 performLayout 函數(shù)。

          1. 如上圖 RenderParagraph 執(zhí)行 performLayout 。首先 _layoutChildren:為子控件布局,目的為獲取子控件大小,如果沒有子控件則直接 return。這里所說的子控件就是 WidgetSpan。

          2. 第二步 _layoutTextWithConstraints,就是執(zhí)行 _textPainter 的 layout 方法,這里會讓 text(InlineSpan)進(jìn)行 build,此時會按照它的樹形結(jié)構(gòu)遍歷執(zhí)行。

          3. TextWidget build 時會將自身的 text(這是真實的字符串)addText 給 builder。

          4. WidgetSpan build 時會將自身控件的 PlaceholderDimensions 信息,addPlaceholder 給 builder。這里其實就是添加占位符,占位符將與控件同大小。

          5. 緊接著 _paragraph 會進(jìn)行一次布局,然后獲取各個占位符位置存儲下來。

          6. Paint 過程會先將帶著占位符的文本繪制完成,然后遍歷子控件按照 2-3 步驟中獲得的占位符位置,設(shè)置偏移。

          概括來說,新版本對比舊版本,底層多了個 _addPlaceholder 能力,用來占位混排的 Widget,并獲取位置信息。

          設(shè)計思路

          我們以 HTML 協(xié)議為抓手,不光可以解決普通 HTML 字符串的解析與渲染,也可以對用戶發(fā)送的帶閑魚自定義 emoji 的字符串進(jìn)行能力的擴(kuò)充。下圖為大致的設(shè)計思路:

          當(dāng)前消息展示分為兩種場景,一種為帶有閑魚自定義 emoji 表情的字符串:

          1. 你好[微笑],你的寶貝不錯哦[呲牙],包郵嗎?[壞笑][壞笑]

          另一種為簡單的 HTML 字符串:

          1. "<fontcolor="#888888">交易全程在閑魚,</font><strong><fontcolor="#F54444">你敢買,我敢賠!</font></strong><fontcolor="#888888">若遇欺詐造成</font><strong><fontcolor="#F54444">錢貨兩失,可獲賠</font></strong><strong><fontcolor="#F54444">最高5000元</font></strong>"

          當(dāng)然,還有最普通的純文本。

          對于這三種字符串,服務(wù)端并沒有用類型來給我們區(qū)分,客戶端拿到的都為字符串。端側(cè)該如何處理且高效展示呢?

          過程設(shè)計成這樣:

          1. 首先對于確定為純文字的控件,直接使用單 TextSpan 的 RichText,免去 Text 的封裝。

          2. 使用 RegExp(r'\[[^\]\[]+\]')匹配[微笑]等 emoji 占位符,替換為<imgsrc=003_微笑.pngwidth=22.400000height=22.400000/>

          3. 取最后的 HTMLString ,使用 html | Dart Package ,進(jìn)行 HTML 解析,生成 HTML Node Tree

          4. 遞歸 HTML Node Tree

          5. 文本標(biāo)簽映射為 TextSpan

          6. 圖片標(biāo)簽映射為 FDImageSpan;Flutter 升級后將其替換為 WidgetSpan,其 child 設(shè)置為 Image Widget

          7. 鏈接標(biāo)簽映射為 TextSpan,定義 GestureRecognizer 相應(yīng)手勢

          流程上,先將閑魚自定義 emoji 占位符轉(zhuǎn)為 HTML 元素,接著統(tǒng)一處理 HTML 字符串。然后將 HTML 字符串統(tǒng)一轉(zhuǎn)為富文本。設(shè)計上,分為兩層:數(shù)據(jù)解析層、渲染層。

          如上圖,有了前面原生 Flutter 圖文混排支撐,我們在低版本可以仿照實現(xiàn),低版本 RichText 繼承自 LeafRenderObjectWidget,我們把 RichText 與其他 Widget 組成新的 MultiChildRenderObjectWidget,通過占位符正常渲染文本,之后獲取占位符位置,設(shè)置對應(yīng) Widget 的位置。

          Flutter SDK 升級過程中如何保持業(yè)務(wù)方無感知?先看下圖:

          對比發(fā)現(xiàn),在 TextSpan 樹中,我們繼承自 TextSpan 的自定義 FDImageSpan,實際上可以直接對應(yīng)到原生的 WidgetSpan,這里我們可以在 HTML Node Tree 映射到 TextSpan Tree 的過程中直接修改。而 FDRichText build 里,我們可以直接返回系統(tǒng) RichText。這樣的改動,對于使用方可以做到無感知。

          效果

          上圖中是一種最為簡單和常見的系統(tǒng)消息,為了突出安全警示,使用了較多的紅色字體。模塊中定義的三個富文本,均可定制樣式。

          上圖為涉及交互的富文本,買家可以點擊藍(lán)色文字「那兒發(fā)貨」,然后買家會自動發(fā)送「那兒發(fā)貨」給賣家,賣家會根據(jù)預(yù)設(shè)的問題自動回復(fù)買家。點擊會觸發(fā) HTML 字符串中的 href 自定義協(xié)議鏈接,客戶端會觸發(fā) openURL 的操作,以此來實現(xiàn)交互。

          這是普通用戶可以編輯發(fā)送的富文本,豐富的閑魚自定義 emoji,穿插在文字中,不僅增加了聊天樂趣,也增強了用戶的表達(dá)。

          后續(xù)計劃

          當(dāng)前的展示部分僅僅是圖文混排,新版本中的富文本支持任意 Widget,可玩性更高,所以我們對 HTML 標(biāo)簽描述可以進(jìn)行擴(kuò)充,這部分未來還需要持續(xù)探索。

          由于篇幅有限,上文并沒有講述富文本編輯器。消息中用戶輸入框也需支持閑魚自定義 emoji,當(dāng)前版本的方案為直接使用占位符(比如“[微笑]”),并不展示實際的圖片。我們回頭再看一下 HTML 協(xié)議,對于新版的 TextField,我們可以支持嗎?這就不僅僅局限在自定義 emoji 里了。

          我們把目光轉(zhuǎn)向發(fā)布和寶貝詳情:

          我們后續(xù)可能會支持上圖中,發(fā)布和寶貝詳情的富文本編輯和展示。對比兩個詳情頁,很明顯能看出,使用富文本的方式,在表達(dá)上更加富有沖擊力,買家閱讀起來能很容易抓住賣家想表達(dá)的關(guān)鍵信息。

          可見,未來在富文本的編輯、展示基礎(chǔ)能力統(tǒng)一之后,可以讓更多業(yè)務(wù)收益。

          閑魚技術(shù)團(tuán)隊不僅是阿里巴巴集團(tuán)旗下閑置交易社區(qū)的創(chuàng)造者,更是移動與高并發(fā)大數(shù)據(jù)應(yīng)用新技術(shù)的引導(dǎo)者與創(chuàng)新者。我們與Google Flutter/Dart小組密切合作,為社區(qū)貢獻(xiàn)了多個高star的項目和大量PR。我們正在積極探索深度學(xué)習(xí)和視覺技術(shù)在互動、交易、社區(qū)場景的創(chuàng)新應(yīng)用。閑魚技術(shù)與集團(tuán)中間件團(tuán)隊共同打造的FaaS平臺每天支持?jǐn)?shù)以千萬級用戶的高并發(fā)訪問場景。

          就是現(xiàn)在!客戶端/服務(wù)端java/架構(gòu)/前端/質(zhì)量工程師面向社會+校園招聘,base杭州阿里巴巴西溪園區(qū),一起做有創(chuàng)想空間的社區(qū)產(chǎn)品、做深度頂級的開源項目,一起拓展技術(shù)邊界成就極致!

          *投喂簡歷給小閑魚→guicai.gxy@alibaba-inc.com

          開源項目、峰會直擊、關(guān)鍵洞察、深度解讀

          請認(rèn)準(zhǔn)閑魚技術(shù)

          在閑魚消息體系中,富文本在 UI 側(cè)占了非常大的比重。最近消息部分在整體 Flutter 化,如何解決 Flutter 側(cè)富文本問題,成為了項目早期的風(fēng)險點。

          在 Native 中,消息使用了 HTML 協(xié)議來承載富文本的解析與展示,由于消息的歷史數(shù)據(jù)有落庫的特性,我們必須在 Flutter 側(cè)兼容這種協(xié)議。對于 Flutter,我們是否可以在兼容的基礎(chǔ)上,進(jìn)行能力的擴(kuò)充與完善?

          當(dāng)前閑魚也在升級 Flutter 1.12,所以我們不光要在當(dāng)前版本支持圖文混排,也需要快速遷移到高版本的系統(tǒng)方案。因此我們需要找到一個兼容性高、易遷移的富文本方案。

          行業(yè)現(xiàn)狀

          行業(yè)內(nèi),對于舊版的 RichText (Flutter 1.7.3 之前)已有了解決方案,詳見玄川:《如何低成本實現(xiàn)Flutter 富文本,看這一篇就夠了!》。但這里并沒有對富文本的整個鏈路的解決思路,且 Flutter 自身的 RichText 也在隨著版本迭代進(jìn)行演進(jìn),我們需要一套完整的演進(jìn)方案。

          事實上,F(xiàn)lutter 1.7.3 開始的 RichText 解決了我們的很多麻煩,它是怎么實現(xiàn)的呢?和舊版的實現(xiàn)有什么區(qū)別呢?帶著問題,我們先來分析它的實現(xiàn)原理。

          RichText圖文混排原理

          Flutter 1.7.3 開始,RichText 不再繼承自 LeafRenderObjectWidget,而是繼承自 MultiChildRenderObjectWidget,從這就很容易看出,RichText 將是一個布局控件,內(nèi)部可以有多個子控件。

          創(chuàng)建過程


          如上圖,我們傳給 RichText 的 text 參數(shù)為 InlineSpan,TextSpan、WidgetSpan都是其子類。

          1. RichText 初始化過程中會將 text 中的所有 WidgetSpan 遞歸篩選出來,傳遞給父類 MultiChildRenderObjectWidget。
          2. 創(chuàng)建 MultiChildRenderObjectElement,接著 RichText 會通過 createRenderObject,生成 RenderParagraph。
          3. RenderParagraph 初始化過程中會創(chuàng)建 TextPainter,這個是繪制的核心,這里將會進(jìn)行 layout、paint 和事件分發(fā)操作;然后遞歸篩選 PlaceholderSpan (其實還是 WidgetSpan)。

          渲染過程


          上圖為 RenderParagraph 內(nèi)的 performLayout 函數(shù)。

          1. 如上圖 RenderParagraph 執(zhí)行 performLayout 。首先 _layoutChildren:為子控件布局,目的為獲取子控件大小,如果沒有子控件則直接 return。這里所說的子控件就是 WidgetSpan。
          2. 第二步 _layoutTextWithConstraints,就是執(zhí)行 _textPainter 的 layout 方法,這里會讓 text(InlineSpan)進(jìn)行 build,此時會按照它的樹形結(jié)構(gòu)遍歷執(zhí)行。
          3. TextWidget build 時會將自身的 text(這是真實的字符串)addText 給 builder。
          4. WidgetSpan build 時會將自身控件的 PlaceholderDimensions 信息,addPlaceholder 給 builder。這里其實就是添加占位符,占位符將與控件同大小。
          5. 緊接著 _paragraph 會進(jìn)行一次布局,然后獲取各個占位符位置存儲下來。
          6. Paint 過程會先將帶著占位符的文本繪制完成,然后遍歷子控件按照 2-3 步驟中獲得的占位符位置,設(shè)置偏移。

          概括來說,新版本對比舊版本,底層多了個 _addPlaceholder 能力,用來占位混排的 Widget,并獲取位置信息。

          設(shè)計思路

          我們以 HTML 協(xié)議為抓手,不光可以解決普通 HTML 字符串的解析與渲染,也可以對用戶發(fā)送的帶閑魚自定義 emoji 的字符串進(jìn)行能力的擴(kuò)充。下圖為大致的設(shè)計思路:

          當(dāng)前消息展示分為兩種場景,一種為帶有閑魚自定義 emoji 表情的字符串:

          你好[微笑],你的寶貝不錯哦[呲牙],包郵嗎?[壞笑][壞笑]

          另一種為簡單的 HTML 字符串:

          "<fontcolor="#888888">交易全程在閑魚,</font><strong><fontcolor="#F54444">你敢買,我敢賠!</font></strong><fontcolor="#888888">若遇欺詐造成</font><strong><fontcolor="#F54444">錢貨兩失,可獲賠</font></strong><strong><fontcolor="#F54444">最高5000元</font></strong>"

          當(dāng)然,還有最普通的純文本。

          對于這三種字符串,服務(wù)端并沒有用類型來給我們區(qū)分,客戶端拿到的都為字符串。端側(cè)該如何處理且高效展示呢?

          過程設(shè)計成這樣:

          1. 首先對于確定為純文字的控件,直接使用單 TextSpan 的 RichText,免去 Text 的封裝。
          2. 使用 RegExp(r'\[[^\]\[]+\]') 匹配 [微笑] 等 emoji 占位符,替換為 <imgsrc=003_微笑.pngwidth=22.400000height=22.400000/>
          3. 取最后的 HTMLString ,使用 html | Dart Package ,進(jìn)行 HTML 解析,生成 HTML Node Tree
          4. 遞歸 HTML Node Tree
          5. 文本標(biāo)簽映射為 TextSpan
          6. 圖片標(biāo)簽映射為 FDImageSpan;Flutter 升級后將其替換為 WidgetSpan,其 child 設(shè)置為 Image Widget
          7. 鏈接標(biāo)簽映射為 TextSpan,定義 GestureRecognizer 相應(yīng)手勢

          流程上,先將閑魚自定義 emoji 占位符轉(zhuǎn)為 HTML 元素,接著統(tǒng)一處理 HTML 字符串。然后將 HTML 字符串統(tǒng)一轉(zhuǎn)為富文本。設(shè)計上,分為兩層:數(shù)據(jù)解析層、渲染層。

          如上圖,有了前面原生 Flutter 圖文混排支撐,我們在低版本可以仿照實現(xiàn),低版本 RichText 繼承自 LeafRenderObjectWidget,我們把 RichText 與其他 Widget 組成新的 MultiChildRenderObjectWidget,通過占位符正常渲染文本,之后獲取占位符位置,設(shè)置對應(yīng) Widget 的位置。

          Flutter SDK 升級過程中如何保持業(yè)務(wù)方無感知?先看下圖:

          對比發(fā)現(xiàn),在 TextSpan 樹中,我們繼承自 TextSpan 的自定義 FDImageSpan,實際上可以直接對應(yīng)到原生的 WidgetSpan,這里我們可以在 HTML Node Tree 映射到 TextSpan Tree 的過程中直接修改。而 FDRichText build 里,我們可以直接返回系統(tǒng) RichText。這樣的改動,對于使用方可以做到無感知。

          效果

          上圖中是一種最為簡單和常見的系統(tǒng)消息,為了突出安全警示,使用了較多的紅色字體。模塊中定義的三個富文本,均可定制樣式。

          上圖為涉及交互的富文本,買家可以點擊藍(lán)色文字「那兒發(fā)貨」,然后買家會自動發(fā)送「那兒發(fā)貨」給賣家,賣家會根據(jù)預(yù)設(shè)的問題自動回復(fù)買家。點擊會觸發(fā) HTML 字符串中的 href 自定義協(xié)議鏈接,客戶端會觸發(fā) openURL 的操作,以此來實現(xiàn)交互。

          這是普通用戶可以編輯發(fā)送的富文本,豐富的閑魚自定義 emoji,穿插在文字中,不僅增加了聊天樂趣,也增強了用戶的表達(dá)。

          后續(xù)計劃

          當(dāng)前的展示部分僅僅是圖文混排,新版本中的富文本支持任意 Widget,可玩性更高,所以我們對 HTML 標(biāo)簽描述可以進(jìn)行擴(kuò)充,這部分未來還需要持續(xù)探索。

          由于篇幅有限,上文并沒有講述富文本編輯器。消息中用戶輸入框也需支持閑魚自定義 emoji,當(dāng)前版本的方案為直接使用占位符(比如“[微笑]”),并不展示實際的圖片。我們回頭再看一下 HTML 協(xié)議,對于新版的 TextField,我們可以支持嗎?這就不僅僅局限在自定義 emoji 里了。

          我們把目光轉(zhuǎn)向發(fā)布和寶貝詳情:

          我們后續(xù)可能會支持上圖中,發(fā)布和寶貝詳情的富文本編輯和展示。對比兩個詳情頁,很明顯能看出,使用富文本的方式,在表達(dá)上更加富有沖擊力,買家閱讀起來能很容易抓住賣家想表達(dá)的關(guān)鍵信息。

          可見,未來在富文本的編輯、展示基礎(chǔ)能力統(tǒng)一之后,可以讓更多業(yè)務(wù)收益。

          育知同創(chuàng)前端培訓(xùn)技術(shù)分享:HTML簡介及常用標(biāo)簽(中)

          七、HTML4.0與HTML5.0的規(guī)范

          Html4.0的基本規(guī)范

          ?標(biāo)簽名和屬性名稱不區(qū)分大小寫

          ?HTML標(biāo)簽不必全部關(guān)閉

          ?屬性值用引號或者不用引號括起來

          ?標(biāo)簽必須正確嵌套

          ?文檔必須擁有一個根元素,所有的XHTML元素必須嵌套于<html>根元素中

          XHTML基本規(guī)范

          ?標(biāo)簽名和屬性名稱必須小寫

          ?HTML標(biāo)簽必須關(guān)閉

          ?屬性值必須用引號括起來

          ?標(biāo)簽必須正確嵌套

          ?文檔必須擁有一個根元素,所有的XHTML元素必須嵌套于<html>根元素中

          Html5的基本規(guī)范:對于html4和xhtml的規(guī)范都可以并對在基礎(chǔ)上又做了簡化。漸進(jìn)增強和優(yōu)雅降級

          八、HTML4.0與HTML5.0的區(qū)別

          D、HTML5新增了一些標(biāo)簽,也廢棄了一些標(biāo)簽

          新增標(biāo)簽

          ?<article>

          ?<aside>

          ?<audio>

          ?<canvas>

          ?<footer>

          ?<header>

          ?<hgroup>

          ?<section>

          ?<time>

          ?<video>

          ?。。。。

          廢棄標(biāo)簽

          a)能用css代替的元素basefont、big、center、font、s、strike、tt、u

          b)不再使用frame框架

          c)只有部分瀏覽器支持的元素applet、bgsound、blink、marquee等標(biāo)簽

          d)其他被廢除的元素 Rb acronym dir isindex listing xmp nextid plaintex

          九、photoshop的基本使用

          我們前面了解了一個網(wǎng)站從無到有的過程,那設(shè)計師給我們是一個效果圖,我們需要把效果圖用photoshopt(我們這里主要講解的是photoshop)等相關(guān)技術(shù)把網(wǎng)頁中的圖片切割下來。

          Photoshop常用快捷鍵

          1. 頁面顯示比例的放大與縮小:Ctrl+加號(放大)、Ctrl+減號(縮小)

          2. 臨時抓手工具:空格

          3. 標(biāo)尺的顯示、隱藏: CTRL+R

          4. 選擇工具的使用

          5. 顯示/隱藏“信息”面板:F8

          6. 選擇框的取消:Ctrl+D

          7. 單位的設(shè)置

          8. 參考線的設(shè)置

          9. 自由變換:Ctrl+T

          10. 切片


          主站蜘蛛池模板: 国产成人一区二区动漫精品| 中文字幕一区二区精品区| 91精品一区国产高清在线| 日韩免费一区二区三区| 国产视频一区在线播放| 99精品一区二区三区无码吞精| 精品亚洲一区二区| 欲色影视天天一区二区三区色香欲| 精品一区二区91| 中文字幕一区二区视频| 久久久久人妻精品一区 | 亚洲一区二区三区乱码A| 麻豆高清免费国产一区| 中文字幕无码免费久久9一区9| 亚洲AV噜噜一区二区三区| 国产一区二区三区91| 后入内射国产一区二区| 精品国产一区二区三区免费| 99偷拍视频精品一区二区 | 国产成人久久精品区一区二区| 日本精品一区二区三区在线视频| 日韩精品区一区二区三VR| 一区二区视频免费观看| 国产一区二区三区福利| 国产精品一区视频| 男人的天堂精品国产一区| 变态调教一区二区三区| 日韩在线视频一区| 亚洲国产精品自在线一区二区| 一区二区三区精品高清视频免费在线播放| 欲色aV无码一区二区人妻| 日韩中文字幕一区| 日本一区二区在线免费观看| 精品中文字幕一区在线| 任你躁国语自产一区在| 免费高清av一区二区三区| 成人H动漫精品一区二区| 国产一区二区三区无码免费| 国产一区二区三区播放心情潘金莲 | 久久精品一区二区三区中文字幕 | 国产精品亚洲专一区二区三区|