成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

鴻蒙開(kāi)源第三方組件—自定義流式布局組件FlowLayout_ohos

系統(tǒng)
本文基于安卓平臺(tái)的自定義流式布局組件FlowLayout,實(shí)現(xiàn)了鴻蒙的功能化遷移和重構(gòu)。代碼已經(jīng)開(kāi)源到(https://gitee.com/isrc_ohos/flow-layout_ohos),歡迎各位開(kāi)發(fā)者下載使用并提出寶貴意見(jiàn)!

[[413476]]

想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

前言

基于安卓平臺(tái)的自定義流式布局組件FlowLayout,實(shí)現(xiàn)了鴻蒙的功能化遷移和重構(gòu)。代碼已經(jīng)開(kāi)源到(https://gitee.com/isrc_ohos/flow-layout_ohos),歡迎各位開(kāi)發(fā)者下載使用并提出寶貴意見(jiàn)!

背景

流式布局也叫百分比布局,它具有指定的對(duì)齊方式、水平間隙和垂直間隙,特別適用于多標(biāo)簽的展示,可以實(shí)現(xiàn)組件中的標(biāo)簽橫向?qū)R,也可以在多個(gè)標(biāo)簽的總寬度超過(guò)組件寬度時(shí)自動(dòng)換行,是移動(dòng)端開(kāi)發(fā)中經(jīng)常使用的布局方式之一。我們可以在很多應(yīng)用場(chǎng)景下看到流式布局的使用,比如商品分類展示,搜索記錄展示等。

組件效果展示

該組件應(yīng)用只包含一個(gè)顯示頁(yè)面。為了呈現(xiàn)出流式布局的效果,我們?cè)陧?yè)面布局中添加了多個(gè)標(biāo)簽,如“java”、“kotlin”、“ohos”、“Deveco-studio”、“app”等作為布局中的子組件。具體顯示效果如圖1所示。

鴻蒙開(kāi)源第三方組件——自定義流式布局組件FlowLayout_ohos-鴻蒙HarmonyOS技術(shù)社區(qū)

圖1 組件效果展示

Sample解析

FlowLayout_ohos在Library中已經(jīng)封裝了組件的主要功能,往FlowLayout_ohos組件中放入標(biāo)簽會(huì)自動(dòng)橫向?qū)R并且在多個(gè)標(biāo)簽的總寬度超過(guò)組件寬度時(shí)自動(dòng)換行,因此在Sample中我們只需要添加標(biāo)簽內(nèi)容并使用流式布局將標(biāo)簽內(nèi)容進(jìn)行顯示即可。

在標(biāo)簽顯示的過(guò)程中,我們可以調(diào)用一些Library暴露的接口來(lái)對(duì)子組件的顯示特征進(jìn)行設(shè)置,比如組件最多顯示的行數(shù)等。下面將具體講解FlowLayout_ohos組件的使用方法,共分為5個(gè)步驟:

步驟1. 導(dǎo)入相關(guān)類

步驟2. 初始化流式布局和數(shù)據(jù)容器

步驟3. 添加標(biāo)簽內(nèi)容到數(shù)據(jù)容器

步驟4. 將標(biāo)簽內(nèi)容添加進(jìn)布局

步驟5. 相關(guān)特征設(shè)置

接下來(lái)我們來(lái)看一下每一個(gè)步驟涉及的詳細(xì)操作。

(1)導(dǎo)入相關(guān)類

在MainAbilitySlice文件中,通過(guò)import關(guān)鍵字導(dǎo)入FlowAdapter類和FlowLayout類。FlowLayout類用于組件的顯示,F(xiàn)lowAdapter類用于向組件設(shè)置標(biāo)簽。

  1. import com.huawei.mylibrary.FlowAdapter; 
  2. import com.huawei.mylibrary.FlowLayout; 

 (2)初始化流式布局和數(shù)據(jù)容器

實(shí)例化FlowLayout類的對(duì)象mFlowLayout ,然后創(chuàng)建元素為String類型的列表mContentList作為添加標(biāo)簽的容器,以下我們稱之為數(shù)據(jù)容器。

  1. private FlowLayout mFlowLayout; 
  2. private List<String> mContentList = new ArrayList<>(); 
  3. @Override  
  4. public void onStart(Intent intent) { 
  5.       ......  
  6.       mFlowLayout = new FlowLayout(this); 

(3)添加標(biāo)簽內(nèi)容到數(shù)據(jù)容器

通過(guò)add()方法向數(shù)據(jù)容器mContentList中添加想要展示的標(biāo)簽,5個(gè)不同的標(biāo)簽通過(guò)for循環(huán)循環(huán)四次逐個(gè)放入容器,共形成20個(gè)需要在頁(yè)面展示的標(biāo)簽。

  1. for (int i = 0; i < 4; i++) { 
  2.       mContentList.add("java"); 
  3.       mContentList.add("kotlin"); 
  4.       mContentList.add("ohos"); 
  5.       mContentList.add("Deveco-studio"); 
  6.       mContentList.add("app");   

(4)將標(biāo)簽內(nèi)容添加進(jìn)布局

實(shí)例化FlowAdapter類的對(duì)象adapter,并將數(shù)據(jù)容器mContentList作為FlowAdapter類構(gòu)造方法的參數(shù)。后通過(guò)setAdapter()方法將標(biāo)簽內(nèi)容添加到組件中。

  1. // 設(shè)置 Adapter 
  2. FlowAdapter adapter = new FlowAdapter(this, mContentList); 
  3. // 將標(biāo)簽內(nèi)容添加到組件中 
  4. mFlowLayout.setAdapter(adapter); 

(5) 將標(biāo)簽內(nèi)容添加到組件中

  1. mFlowLayout.setAdapter(adapter); 

(6)相關(guān)特征設(shè)置

mFlowLayout可以調(diào)用一些Library暴露的接口實(shí)現(xiàn)流式布局的特征設(shè)置,這里我們?cè)O(shè)置了組件布局內(nèi)最多顯示的行數(shù)。

  1. // 設(shè)置最多顯示的行數(shù) 
  2. mFlowLayout.setMaxLines(9); 

Library解析

流式布局應(yīng)用非常廣泛,但鴻蒙官方卻并未給出相應(yīng)的布局方式,因此流式布局只能自定義實(shí)現(xiàn),本節(jié)主要介紹自定義布局的步驟。

想要實(shí)現(xiàn)自定義布局,需要完成以下三個(gè)步驟:1)流式布局的FlowLayout類需要繼承ComponentContainer類,并添加構(gòu)造方法。2) 實(shí)現(xiàn)ComponentContainer.EstimateSizeListener接口,重寫(xiě)onEstimateSize()方法,用于確定FlowLayout_ohos組件寬高。3)實(shí)現(xiàn)Component.LayoutRefreshedListener接口,重寫(xiě)onRefreshed()方法用來(lái)排列子組件并確定子組件位置。1)步驟的操作較為簡(jiǎn)單,此處不再贅述,本節(jié)主要描述2)、3)步驟的原理。

(1)重寫(xiě)onEstimateSize方法

根據(jù)onEstimateSize(int widthMeasureSpec, int heightMeasureSpec)方法傳入的參數(shù),選擇測(cè)量組件寬度和高度的方式,并得到組件寬度和高度的具體值,通過(guò)setEstimatedSize()方法設(shè)置給組件。下面介紹具體的步驟:

1、得到組件的測(cè)量模式和父組件的寬度、高度

  • 調(diào)用EstimateSpec.getMode(widthMeasureSpec)方法,傳入widthMeasureSpec參數(shù),得到組件寬度的測(cè)量模式。
  • 調(diào)用EstimateSpec.getMode(heightMeasureSpec)方法,傳入heightMeasureSpec參數(shù),得到組件高度的測(cè)量模式。
  • 調(diào)用EstimateSpec.getSize(widthMeasureSpec)方法,傳入widthMeasureSpec參數(shù),得到父組件的寬度。
  • 調(diào)用EstimateSpec.getSize(heightMeasureSpec)方法,傳入heightMeasureSpec參數(shù),得到父組件的高度。
  1. int widthSize = EstimateSpec.getSize(widthMeasureSpec);//父組件的寬度 
  2. int widthMode = EstimateSpec.getMode(widthMeasureSpec); //組件寬度的測(cè)量模式 
  3. int heightSize =EstimateSpec.getSize(heightMeasureSpec);//父組件的高度 
  4. int heightMode = EstimateSpec.getMode(heightMeasureSpec);//組件高度的測(cè)量模式 

2、確定組件寬度和高度的具體值

widthMode /heightMode 可能存在兩種不同的模式,在不同的模式下組件的寬度和高度的值也會(huì)有不同的計(jì)算方式。

  • PRECISE 模式:在這種模式下,組件設(shè)置其寬、高為MATCH_PARENT。
  • NOT_EXCEED 模式:在這種模式下,組件設(shè)置其寬、高為MATCH_CONTENT 。

在PRECISE 模式下,組件的寬度和高度與父組件一致,這種計(jì)算方式較為簡(jiǎn)單。但是在NOT_EXCEED 模式下,組件的寬度和高度是根據(jù)子組件的寬度和高度來(lái)決定的,此時(shí)需要遍歷各子組件,對(duì)每個(gè)子組件進(jìn)行測(cè)量,并在寬度和高度上求和,才能計(jì)算出最終的組件的寬高。子組件的遍歷過(guò)程是通過(guò)helper()方法來(lái)實(shí)現(xiàn)的。

  1. int[] a = helper(widthSize);  
  2. int measuredHeight = 0;   //組件的高度值 
  3. if (heightMode == EstimateSpec.PRECISE) {  // PRECISE 模式 
  4.     measuredHeight = heightSize; 
  5. else if (heightMode == EstimateSpec.NOT_EXCEED) {  // NOT_EXCEED 模式 
  6.     measuredHeight = a[0]; //遍歷各子組件后得到的組件高度 
  7. int measuredWidth = 0;   //組件的寬度值 
  8. if (widthMode == EstimateSpec.PRECISE) {        // PRECISE 模式 
  9.     measuredWidth = widthSize;    
  10. }else if (widthMode == EstimateSpec.NOT_EXCEED) { // NOT_EXCEED 模式 
  11.     measuredWidth = a[1];  //遍歷各子組件后得到的組件寬度 

3、將測(cè)量得到的高度和寬度值設(shè)置給組件。

通過(guò)setEstimatedSize()方法,將步驟2中得到的組件寬度和高度值設(shè)置給組件。

  1. setEstimatedSize(measuredWidth, measuredHeight); 

(2)重寫(xiě)onRefreshed方法

onRefreshed()方法主要用來(lái)確定子組件的擺放位置。該位置在helper()方法中已經(jīng)得到,并保存在mChildrenPositionList中。mChildrenPositionList是一個(gè)元素類型為Rect的列表,每一個(gè)元素代表一個(gè)子組件的位置信息。因此,在確定子組件的擺放位置時(shí),只需要調(diào)用mChildrenPositionList中的元素信息,并將其賦給各子組件即可。

  1. @Override 
  2. public void onRefreshed(Component component) { 
  3.             int n = Math.min(getChildCount(), mChildrenPositionList.size()); 
  4.             for (int i = 0; i < n; i++) { 
  5.                 Component child = getComponentAt(i);  //獲取各組件 
  6.                 Rect rect = mChildrenPositionList.get(i); //組件信息 
  7.                 child.setLeft(rect.left);  //組件位置設(shè)置 
  8.                 child.setRight(rect.right); 
  9.                 child.setBottom(rect.bottom); 
  10.                 child.setTop( rect.top); 
  11.             } 
  12.             mVisibleItemCount = n; 
  13.     } 

(3)helper()方法

helper()方法是一個(gè)“工具”方法,在onEstimateSize()和onRefreshed()的重寫(xiě)中都提供了“幫助”。helper()方法對(duì)外提供的功能,主要為以下三個(gè)方面:

1)在組件的布局方式為MATCH_CONTENT情況下,遍歷各子組件,對(duì)每個(gè)子組件的寬度和高度進(jìn)行測(cè)量,并在寬度和高度上求和,計(jì)算出最終組件的寬度和高度。

2)判斷換行條件,實(shí)現(xiàn)流動(dòng)布局的效果。

3)保存子組件的位置信息。

下面我們將圍繞上述內(nèi)容展開(kāi)講解。

1)計(jì)算組件寬度和高度

  • 組件的寬度

組件的寬度取決于子組件的排布是否存在換行的情況,若是子組件排布存在換行的情況,組件寬度等于父組件的寬度。若是子組件排布不存在換行的情況,組件寬度等于當(dāng)前行的寬度。代碼中isOneRow表示是否存在換行的情況,width 表示當(dāng)前行的寬度,widthSize表示父組件的寬度,各變量的示意如圖2所示。

鴻蒙開(kāi)源第三方組件——自定義流式布局組件FlowLayout_ohos-鴻蒙HarmonyOS技術(shù)社區(qū)

圖2 代碼變量示意圖

  1. int childWidth =  child.getMarginLeft() + child.getEstimatedWidth() + child.getMarginRight(); //每個(gè)子組件的寬度 
  2. width += childWidth;  //每行的寬度 
  3. ... 
  4. res[1] = isOneRow? width + getPaddingRight() : widthSize; //組件的寬度 
  • 組件的高度

組件的高度是每一行子組件高度的總和,而每一行的高度則是取該行中所有子組件中最高的值。

  1. int childHeight =child.getMarginTop() + child.getEstimatedHeight() + child.getMarginBottom(); 
  2. maxHeight = Math.max(maxHeight, childHeight); //取最大值 
  3. ... 
  4. res[0] = height + maxHeight + getPaddingBottom(); //組件的高度  

2)判斷換行條件

從效果圖中可以看到,F(xiàn)lowLayout_ohos組件的布局是一行行的,如果當(dāng)前行的剩余寬度已經(jīng)放不了下一個(gè)子組件,那就把這個(gè)子組件移到下一行顯示。

所以我們需要計(jì)算當(dāng)前行已經(jīng)占據(jù)的寬度加上下一個(gè)子組件的寬度是否超過(guò)組件的最大寬度,以判斷下一個(gè)子組件是否需要換行顯示。

  1. if (width + childWidth + getPaddingRight() > widthSize) { //需要換行 
  2.    height += maxHeight; // 增加一行的高度 
  3.     width = getPaddingLeft(); // 獲取新一行已經(jīng)占據(jù)的寬度 
  4.     maxHeight = childHeight;  
  5.    isOneRow = false
  6.    currLine++;  //行數(shù)+1 
  7.     if (currLine > mMaxLines) {  //超過(guò)設(shè)定的最大顯示行數(shù),退出 
  8.         break; 
  9.    } 

3)保存子組件的位置信息

根據(jù)當(dāng)前已有的寬高,確定子組件的位置,并將位置信息作為參數(shù)傳入Rect 類實(shí)例化對(duì)象的過(guò)程中,用Rect 類對(duì)象標(biāo)識(shí)子組件的位置信息,并將這些信息逐個(gè)放入List中,在onRefreshed()方法中被使用到。

  1. Rect rect = new Rect(width +child.getMarginLeft(), 
  2.         height + child.getMarginTop(), 
  3.         width + childWidth - child.getMarginRight(), 
  4.         height + childHeight - child.getMarginBottom()); 
  5. mChildrenPositionList.add(rect); 

想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

 

責(zé)任編輯:jianghua 來(lái)源: 鴻蒙社區(qū)
相關(guān)推薦

2021-06-17 14:56:00

鴻蒙HarmonyOS應(yīng)用

2021-07-06 18:21:31

鴻蒙HarmonyOS應(yīng)用

2021-04-08 14:57:52

鴻蒙HarmonyOS應(yīng)用

2021-04-20 15:06:42

鴻蒙HarmonyOS應(yīng)用

2021-08-30 17:55:58

鴻蒙HarmonyOS應(yīng)用

2021-11-17 15:37:43

鴻蒙HarmonyOS應(yīng)用

2021-07-20 15:20:40

鴻蒙HarmonyOS應(yīng)用

2021-04-15 17:47:38

鴻蒙HarmonyOS應(yīng)用

2021-11-02 14:54:21

鴻蒙HarmonyOS應(yīng)用

2021-08-10 15:23:08

鴻蒙HarmonyOS應(yīng)用

2021-10-19 10:04:51

鴻蒙HarmonyOS應(yīng)用

2021-06-29 09:28:16

鴻蒙HarmonyOS應(yīng)用

2021-04-29 14:32:24

鴻蒙HarmonyOS應(yīng)用

2021-03-10 15:03:40

鴻蒙HarmonyOS應(yīng)用

2021-03-24 09:30:49

鴻蒙HarmonyOS應(yīng)用

2021-03-03 09:42:26

鴻蒙HarmonyOS圖片裁剪

2021-08-03 10:07:41

鴻蒙HarmonyOS應(yīng)用

2021-03-01 14:00:11

鴻蒙HarmonyOS應(yīng)用

2021-08-26 16:07:46

鴻蒙HarmonyOS應(yīng)用

2021-08-05 15:06:30

鴻蒙HarmonyOS應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 999re5这里只有精品 | 国产丝袜一区二区三区免费视频 | 一级毛片视频 | 久久久久久久综合色一本 | 国产激情精品 | 日韩一区二区三区在线观看视频 | 国产精品a久久久久 | 国产一区二区三区四区 | 国产一区在线免费 | 性高湖久久久久久久久3小时 | 一区二区日本 | 欧美精品一区三区 | 一本一道久久a久久精品综合蜜臀 | 国产毛片久久久久久久久春天 | 五月天婷婷丁香 | 成人性生交大免费 | 中文字幕不卡视频在线观看 | 日韩欧美一区二区三区 | 国产精品色综合 | 亚洲成人精品一区 | 久久一区二区精品 | 九九爱这里只有精品 | 九色.com| 久久久久久国产精品免费免费男同 | 亚洲成人免费视频在线 | 伊人春色成人网 | 精品亚洲一区二区三区四区五区 | 黄色一级毛片 | 中文字幕精品一区 | 久久久精品视 | 日韩av成人在线 | 国产美女久久 | 国产美女黄色片 | 999在线精品| 美女操网站 | 久久的色 | 青青草一区二区 | 成人欧美一区二区三区在线播放 | 午夜在线观看免费 | 激情毛片 | 一区二区三区四区不卡视频 |