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

鴻蒙開源第三方組件—自定義流式布局組件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ā)者下載使用并提出寶貴意見!

背景

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

組件效果展示

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

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

圖1 組件效果展示

Sample解析

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

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

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

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

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

步驟4. 將標簽內(nèi)容添加進布局

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

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

(1)導入相關(guān)類

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

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

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

實例化FlowLayout類的對象mFlowLayout ,然后創(chuàng)建元素為String類型的列表mContentList作為添加標簽的容器,以下我們稱之為數(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)添加標簽內(nèi)容到數(shù)據(jù)容器

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

  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)將標簽內(nèi)容添加進布局

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

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

(5) 將標簽內(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ù)子組件的寬度和高度來決定的,此時需要遍歷各子組件,對每個子組件進行測量,并在寬度和高度上求和,才能計算出最終的組件的寬高。子組件的遍歷過程是通過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情況下,遍歷各子組件,對每個子組件的寬度和高度進行測量,并在寬度和高度上求和,計算出最終組件的寬度和高度。

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

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

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

1)計算組件寬度和高度

  • 組件的寬度

組件的寬度取決于子組件的排布是否存在換行的情況,若是子組件排布存在換行的情況,組件寬度等于父組件的寬度。若是子組件排布不存在換行的情況,組件寬度等于當前行的寬度。代碼中isOneRow表示是否存在換行的情況,width 表示當前行的寬度,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組件的布局是一行行的,如果當前行的剩余寬度已經(jī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ù)當前已有的寬高,確定子組件的位置,并將位置信息作為參數(shù)傳入Rect 類實例化對象的過程中,用Rect 類對象標識子組件的位置信息,并將這些信息逐個放入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

 

責任編輯:jianghua 來源: 鴻蒙社區(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-08-30 17:55:58

鴻蒙HarmonyOS應(yīng)用

2021-04-20 15:06:42

鴻蒙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-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ù)棧公眾號

主站蜘蛛池模板: 99精品国产一区二区三区 | 夜夜爽99久久国产综合精品女不卡 | 自拍视频一区二区三区 | 亚洲www啪成人一区二区 | 三级成人片 | 色综合天天综合网国产成人网 | 福利视频三区 | 在线播放亚洲 | 丁香婷婷综合激情五月色 | 国产高清免费在线 | 久久99精品久久久久婷婷 | 中文字幕二区 | h片在线播放 | www国产亚洲精品久久网站 | 国产亚洲成av人片在线观看桃 | 拍戏被cao翻了h承欢 | 日韩视频在线播放 | 久久精品99国产精品 | 天堂一区二区三区 | 欧美视频一区 | 奇米超碰在线 | 天天艹逼网 | 日韩av在线播 | 91大神在线资源观看无广告 | h视频免费在线观看 | 亚洲精品美女在线观看 | 日本超碰 | 丁香久久 | 免费成人高清在线视频 | 日韩一区二 | 黄色在线免费观看视频网站 | 亚洲一区二区久久 | 99精品国产一区二区青青牛奶 | 午夜精品一区二区三区在线观看 | 亚洲日韩中文字幕一区 | 国产精品久久久久久吹潮 | 精品国产欧美 | 国产精品不卡一区 | 黄色毛片在线观看 | 欧美日韩一区二区三区四区五区 | 中文字幕 在线观看 |