自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

鴻蒙開源第三方組件—自定義流式布局組件FlowLayout_ohos

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

[[413476]]

想了解更多內(nèi)容,請訪問:

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

https://harmonyos.51cto.com

前言

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

背景

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

組件效果展示

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

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

圖1 組件效果展示

Sample解析

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

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

步驟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è)置

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

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

在MainAbilitySlice文件中,通過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ù)容器

實例化FlowLayout類的對象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ù)容器

通過add()方法向數(shù)據(jù)容器mContentList中添加想要展示的標(biāo)簽,5個不同的標(biāo)簽通過for循環(huán)循環(huán)四次逐個放入容器,共形成20個需要在頁面展示的標(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)布局

實例化FlowAdapter類的對象adapter,并將數(shù)據(jù)容器mContentList作為FlowAdapter類構(gòu)造方法的參數(shù)。后通過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暴露的接口實現(xiàn)流式布局的特征設(shè)置,這里我們設(shè)置了組件布局內(nèi)最多顯示的行數(shù)。

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

Library解析

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

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

(1)重寫onEstimateSize方法

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

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

  • 調(diào)用EstimateSpec.getMode(widthMeasureSpec)方法,傳入widthMeasureSpec參數(shù),得到組件寬度的測量模式。
  • 調(diào)用EstimateSpec.getMode(heightMeasureSpec)方法,傳入heightMeasureSpec參數(shù),得到組件高度的測量模式。
  • 調(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); //組件寬度的測量模式 
  3. int heightSize =EstimateSpec.getSize(heightMeasureSpec);//父組件的高度 
  4. int heightMode = EstimateSpec.getMode(heightMeasureSpec);//組件高度的測量模式 

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

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

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

在PRECISE 模式下,組件的寬度和高度與父組件一致,這種計算方式較為簡單。但是在NOT_EXCEED 模式下,組件的寬度和高度是根據(jù)子組件的寬度和高度來決定的,此時需要遍歷各子組件,對每個子組件進(jìn)行測量,并在寬度和高度上求和,才能計算出最終的組件的寬高。子組件的遍歷過程是通過helper()方法來實現(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、將測量得到的高度和寬度值設(shè)置給組件。

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

  1. setEstimatedSize(measuredWidth, measuredHeight); 

(2)重寫onRefreshed方法

onRefreshed()方法主要用來確定子組件的擺放位置。該位置在helper()方法中已經(jīng)得到,并保存在mChildrenPositionList中。mChildrenPositionList是一個元素類型為Rect的列表,每一個元素代表一個子組件的位置信息。因此,在確定子組件的擺放位置時,只需要調(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()方法是一個“工具”方法,在onEstimateSize()和onRefreshed()的重寫中都提供了“幫助”。helper()方法對外提供的功能,主要為以下三個方面:

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

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

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

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

1)計算組件寬度和高度

  • 組件的寬度

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

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

圖2 代碼變量示意圖

  1. int childWidth =  child.getMarginLeft() + child.getEstimatedWidth() + child.getMarginRight(); //每個子組件的寬度 
  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)放不了下一個子組件,那就把這個子組件移到下一行顯示。

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

  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) {  //超過設(shè)定的最大顯示行數(shù),退出 
  8.         break; 
  9.    } 

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

根據(jù)當(dāng)前已有的寬高,確定子組件的位置,并將位置信息作為參數(shù)傳入Rect 類實例化對象的過程中,用Rect 類對象標(biāo)識子組件的位置信息,并將這些信息逐個放入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)容,請訪問:

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

https://harmonyos.51cto.com

 

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

2021-06-17 14:56:00

鴻蒙HarmonyOS應(yīng)用

2021-04-08 14:57:52

鴻蒙HarmonyOS應(yīng)用

2021-04-20 15:06:42

鴻蒙HarmonyOS應(yīng)用

2021-07-06 18:21:31

鴻蒙HarmonyOS應(yīng)用

2021-08-30 17:55:58

鴻蒙HarmonyOS應(yīng)用

2021-11-17 15:37:43

鴻蒙HarmonyOS應(yīng)用

2021-04-15 17:47:38

鴻蒙HarmonyOS應(yīng)用

2021-07-20 15:20:40

鴻蒙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-03-10 15:03:40

鴻蒙HarmonyOS應(yīng)用

2021-04-29 14:32:24

鴻蒙HarmonyOS應(yīng)用

2021-03-24 09:30:49

鴻蒙HarmonyOS應(yīng)用

2021-03-03 09:42:26

鴻蒙HarmonyOS圖片裁剪

2021-08-26 16:07:46

鴻蒙HarmonyOS應(yīng)用

2021-08-03 10:07:41

鴻蒙HarmonyOS應(yīng)用

2021-03-01 14:00:11

鴻蒙HarmonyOS應(yīng)用

2021-08-05 15:06:30

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

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