超簡(jiǎn)單android自定義控件流式布局SimpleFlowLayout

技術(shù)的進(jìn)步箱蝠,總是由需求推動(dòng)的 ——安卓君

1、前言

流式布局是app開發(fā)中必不可少的布局方式汇陆,例如照片墻怒炸,篩選標(biāo)簽等等≌贝基本上每個(gè)app里面都可以看到這樣的布局阅羹,但是android API中并沒(méi)有提供實(shí)現(xiàn)流式布局方式的控件,因此自己實(shí)現(xiàn)一個(gè)流式布局的控件就非常有必要了教寂。本文分享筆者實(shí)現(xiàn)FlowLayout思考過(guò)程灯蝴,希望能夠拋轉(zhuǎn)引玉,為大家提供一個(gè)新的思路,文章末尾有代碼鏈接孝宗。

2、效果

下面是效果圖:

SimpleFlowLayout示例圖

3耕肩、分析

實(shí)現(xiàn)自定義控件肯定要從View的繪制原理開始思考因妇,關(guān)于View的繪制原理這里就不做介紹了。首先可以確定的是我們要實(shí)現(xiàn)的是一個(gè)ViewGroup猿诸,多個(gè)標(biāo)簽(子控件(View)) 被放置到ViewGroup中婚被。所以要實(shí)現(xiàn)的有:

  • 1.測(cè)量父控件(ViewGroup)的大小
  • 2.放置子控件(View)

體現(xiàn)在代碼中就是實(shí)現(xiàn)父控件的兩個(gè)方法:

  • 1.onMeasure()
  • 2.onLayout()

3.1、計(jì)算父控件的寬高

3.1.1 計(jì)算父控件寬度

流式布局寬度一般都是指定的梳虽,match_parent 或者具體數(shù)值址芯。測(cè)量模式為MeasureSpec.EXACTLY,可以通過(guò)MeasureSpec.getSize(widthMeasureSpec);方法獲取窜觉。如果不是指定寬度谷炸,就無(wú)法換行擺放子控件,流式布局也就不存在了禀挫。

3.1.2 計(jì)算父控件的高度

結(jié)合效果圖看旬陡,父控件的高度由子控件行數(shù)決定的,本文假設(shè)每個(gè)子控件高度一致语婴,行間距一致描孟,間隔一致。

父控件高度 = paddingTop + paddingBottom + 行高*行數(shù) + 行間距*(行數(shù) - 1)
計(jì)算高度

可以看到計(jì)算高度的關(guān)鍵是\color{red}{行數(shù)}\,所以剩下的問(wèn)題就是如何計(jì)算行數(shù)砰左。

如何計(jì)算行數(shù)?

計(jì)算行數(shù)的關(guān)鍵在于知道什么時(shí)候換行匿醒,我們先看看效果圖每一行子控件實(shí)際占據(jù)的寬度


計(jì)算寬度

在FlowLayout中,一行子控件實(shí)際占據(jù)寬度為

行寬度 = 子控件寬度 + 間隔 ... (間隔數(shù)比子控件少一個(gè))

所以我們可以很容易得出這樣一個(gè)換行條件

paddingLeft + 行寬度 +  下一個(gè)子控件的寬度 + paddingRight > 父控件寬度

我們可以通過(guò)for循環(huán)遍歷子控件集合計(jì)算出總行數(shù)缠导,當(dāng)我們得出行數(shù)時(shí)廉羔,就可以計(jì)算出父控件的高度,測(cè)量寬高的工作就完成了僻造。

3.2 放置子控件

放置子控件蜜另,最終調(diào)用

layout(int l, int t, int r, int b)

所以只要得到每個(gè)子控件的位置信息就可以最終展現(xiàn)出流式布局适室,很多人在實(shí)現(xiàn)FlowLayout時(shí),會(huì)在這里重新測(cè)量再計(jì)算子控件的位置举瑰,我覺(jué)得比較繁瑣捣辆,而且重復(fù)的測(cè)量也耗費(fèi)資源。我想到此迅,在onMeasure()方法中汽畴,需要遍歷子控件計(jì)算寬高,那么為什么不在遍歷的時(shí)候耸序,計(jì)算出每個(gè)子控件的位置忍些,再通過(guò)setTag()方法把位置信息賦值給子控件呢?那樣的話在執(zhí)行onLayout()方法坎怪,放置子控件的時(shí)候罢坝,就可以通過(guò)遍歷子控件,getTag() 得到每個(gè)子控件的位置信息搅窿,就可以實(shí)現(xiàn)所有子控件的放置了嘁酿。

如何計(jì)算每個(gè)子控件的位置?

計(jì)算子控件位置

如上圖所示男应,只要計(jì)算出子控件的寬高闹司,我們很容易就能得出left,top,bottom,right值沐飘。

4.實(shí)現(xiàn)單選和多選

如何實(shí)現(xiàn)子控件的單選功能游桩?

可以借鑒RadioGroup實(shí)現(xiàn)原理,也可以換一種思路耐朴,直接繼承RadioGroup就可以實(shí)現(xiàn)單選的功能借卧,添加RadioButton作為子控件,相當(dāng)于把RadioGroup改造成具有流式布局功能的控件筛峭。

如何實(shí)現(xiàn)子控件的多選功能谓娃?

如果添加的子控件都是CheckBox,就可以實(shí)現(xiàn)多選的功能蜒滩。

5.總結(jié)

FlowLayout算不上非常復(fù)雜的控件滨达,原理也很簡(jiǎn)單,一個(gè)是計(jì)算父容器的寬高俯艰,一個(gè)是獲取子控件的位置捡遍。本文從筆者實(shí)際業(yè)務(wù)出發(fā),行間距竹握,間隔都是在自定義屬性中設(shè)置的固定值画株,實(shí)現(xiàn)起來(lái)也簡(jiǎn)單。自認(rèn)為本文特別之處在于,提供新的思路谓传,讓流式布局實(shí)現(xiàn)起來(lái)更簡(jiǎn)單優(yōu)雅

在測(cè)量子控件時(shí)蜈项,計(jì)算每個(gè)控件的位置,并設(shè)置到子控件

本文主要分享思考過(guò)程续挟、實(shí)現(xiàn)方法紧卒,不能說(shuō)多完美,希望能帶給大家一點(diǎn)啟發(fā)诗祸。作者歡迎評(píng)論跑芳,探討!
源碼地址:https://github.com/f1mert/SimpleFlowLayout 歡迎點(diǎn)擊直颅!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末博个,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子功偿,更是在濱河造成了極大的恐慌盆佣,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件械荷,死亡現(xiàn)場(chǎng)離奇詭異共耍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)养葵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瘩缆,“玉大人关拒,你說(shuō)我怎么就攤上這事∮褂椋” “怎么了着绊?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)熟尉。 經(jīng)常有香客問(wèn)我归露,道長(zhǎng),這世上最難降的妖魔是什么斤儿? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任剧包,我火速辦了婚禮,結(jié)果婚禮上往果,老公的妹妹穿的比我還像新娘疆液。我一直安慰自己,他們只是感情好陕贮,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布堕油。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掉缺。 梳的紋絲不亂的頭發(fā)上卜录,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音眶明,去河邊找鬼艰毒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赘来,可吹牛的內(nèi)容都是我干的现喳。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼犬辰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼嗦篱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起幌缝,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灸促,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后涵卵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浴栽,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年轿偎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了典鸡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坏晦,死狀恐怖萝玷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昆婿,我是刑警寧澤球碉,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站仓蛆,受9級(jí)特大地震影響睁冬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜看疙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一豆拨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧能庆,春花似錦辽装、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)殉挽。三九已至,卻和暖如春拓巧,著一層夾襖步出監(jiān)牢的瞬間斯碌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工肛度, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留傻唾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓承耿,卻偏偏與公主長(zhǎng)得像冠骄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子加袋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 自定義View是Android開發(fā)中最普通的需求凛辣,靈活控制View的尺寸是開發(fā)者面臨的第一個(gè)問(wèn)題,比如职烧,為什么明明...
    看書的小蝸牛閱讀 17,391評(píng)論 6 65
  • 問(wèn)答題47 /72 常見(jiàn)瀏覽器兼容性問(wèn)題與解決方案扁誓? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,761評(píng)論 1 92
  • 該文為匯總網(wǎng)上優(yōu)秀的資源所得,喜歡請(qǐng)關(guān)注原作者蚀之,我記錄下來(lái)主要是為了以后我自己查找用的ref 參考啟艦Androi...
    richy_閱讀 1,113評(píng)論 3 16
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,113評(píng)論 1 32
  • iOS布局體系的概覽 在我的CSDN博客中的幾篇文章分別介紹MyLayout布局體系中的視圖從一個(gè)方向依次排列...
    歐陽(yáng)大哥2013閱讀 10,757評(píng)論 11 91