在今年肮塞,2016年的Google i/o 大會上控嗜,Google推出了Android studio2.2橱野,其中包含了為Android界面布局推出的最新的約束型布局ConstraintLayout硫麻,接觸過iOS界面開發(fā)的朋友弟断,可以認(rèn)為這是Google為Android推出的AutoLayout布局洒敏。因為這方面的資料還不是很多龄恋,大部分的資料都是Google官方介紹翻譯,沒有具體用在項目里的實例桐玻,在此正好公司項目中遇到一個問題篙挽,用ConstraintLayout解決了,期間也遇到點困難镊靴。在這里我寫出來铣卡,希望可以幫助到大家,也為了推廣這種布局偏竟,希望大家可以使用煮落。
如圖,需求是一個時間軸控件踊谋,使用ListView實現(xiàn)蝉仇。
每個adapter中包含:
- 一個ImageView,表示時間軸中的進(jìn)度點
- 進(jìn)度點,上面的線line_top(View)
- 進(jìn)度點轿衔,下面的線line_bottom(View)
- 兩個TextView沉迹,分別是進(jìn)度說明,和時間
- 一條橫向的線line(View)
最終做出來的效果圖如下
現(xiàn)在我們分析一下這個效果圖:
- 進(jìn)度點有兩種形態(tài)害驹,大小不一鞭呕;
- 兩個進(jìn)度點之間的連線顏色可以改變;
- 進(jìn)度點宛官,上下的兩條線葫松,3個控件需要中心對齊;
- 進(jìn)度點需要跟第一個的TextView第一行水平對齊底洗,說明上半部分線高度可以固定腋么;
- 第一個TextView行數(shù)不確定,說明下半部分線長度不確定亥揖;
- 橫向的虛線左端與兩個TextView保持在同一Y軸上珊擂,同時右端頂?shù)狡聊蛔钣疫叀?/li>
上面這6點是布局中需要注意的,不變的部分很容易徐块,我們只需要關(guān)注變的部分未玻,再精減一下:
- 進(jìn)度點下面的線高度,可變胡控;
- 第一個TextView行數(shù)扳剿,可變;
- 橫向的灰色線長度要隨著設(shè)備寬度變化昼激;
再剖析一下庇绽,上面3點中,2橙困,3兩點很容易在RelativeLayout中實現(xiàn)瞧掺,但是1的高度,是根據(jù)TextView的行高來實現(xiàn)的凡傅,既1的變化辟狈,依據(jù)2的變化。
可惜的是夏跷,我在用RelativeLayout哼转,實現(xiàn)這3點的時候,發(fā)現(xiàn)下部的線高度不能自動保持跟第一個TextView槽华,一樣的高度壹蔓,只能保持一行的高度,個人認(rèn)為是TextView調(diào)用setText()方法時猫态,通知了TextView的重新繪制佣蓉,但是下部分的線沒有重新繪制披摄,這也許是RelativeLayout的不足之處。個人愚見勇凭,還有待探究疚膊。
因為我想用xml就把布局關(guān)系完成,不需要再代碼里面在操作布局關(guān)系套像,通知繪制酿联,所以就想到了新布局,ConstraintLayout約束布局夺巩。
下面開始:
第一步:創(chuàng)建布局,擺放控件
轉(zhuǎn)換成為ContraintLayout
把需要的控件都放進(jìn)去周崭,如下圖柳譬,大概擺好
現(xiàn)在我們看到的大概的位置,沒有添加任何約束续镇。
第二部:添加約束
對于約束美澳,每一個控件至少水平方向,垂直方向各有一個約束摸航,才能使視圖不會報錯制跟,想讓自己的布局完美展現(xiàn)在手機上,我們應(yīng)該消除所有警報酱虎。
首先我們知道line_top位置和長度都是固定的雨膨,這里我讓它距離屏幕左邊30dp,高度設(shè)置為12dp读串。鼠標(biāo)放在line_top上聊记,會出現(xiàn)4個空心圈。這4個空心圈代表著line_top恢暖,上下左右都沒有設(shè)置約束排监,我們想讓line_top距離左邊30dp,鼠標(biāo)點擊左邊的空心圈杰捂,按住不松舆床,拖至屏幕左邊沿,會出現(xiàn)如下圖嫁佳,松開就設(shè)置了一個約束挨队,
這時我們觀察,界面左邊欄脱拼。如下圖:
按照上面的操作瞒瘸,再把line_top上方設(shè)置一個約束,距離頂部0dp熄浓。這樣line_top這條線就被固定住了情臭。
現(xiàn)在我們之后所有的控件都直接依賴或者間接依賴這個line_top控件省撑,進(jìn)行布局。
下面我們將進(jìn)度點ImageView這個控件俯在,與line_top中心對其竟秫,如下圖:
ImageView左右兩邊都設(shè)置約束,分別對line_top左右兩邊對齊跷乐,這時進(jìn)度點ImageView自動中心對齊了line_top肥败。很簡單,但是我一開始就想不到愕提,也是試了半天才知道要這么設(shè)置馒稍。
這時,我們要開始布局下一個控件了么浅侨?不纽谒,我們應(yīng)該檢查剛剛的Imageview有沒有滿足下面這條準(zhǔn)則:
對于約束,每一個控件至少水平方向如输,垂直方向各有一個約束鼓黔,才能使視圖不會報錯,想讓自己的布局完美展現(xiàn)在手機上不见,我們應(yīng)該消除所有警報澳化。
顯然這個進(jìn)度點在垂直放向缺少一個約束,我們讓他上方距離line_top有3dp的距離
ok稳吮,此時我們設(shè)置下一個控件缎谷,第一個TextView,TextView上方與進(jìn)度點ImageView上方水平對齊盖高,?我們拉住TextView上方的空心圈慎陵,移到ImageView的上方,送手喻奥,就完成了水平對齊
再設(shè)置左邊到ImageView右邊距離為16dp席纽。完成如下圖:
接下來我們讓第二個TextView完成它的約束,我就不細(xì)講了撞蚕,相信你們也明白怎么用了润梯,如下圖:
下面是重點了,line_bottom的約束我們怎么設(shè)置:
這里我們看到有兩個約束甥厦,一個是左邊與line_top左邊對齊纺铭,這樣因為line_top已經(jīng)與ImageView中心對齊,所以line_bottom這樣也會跟ImageView中心對齊刀疙,但是我們知道line_bottom長度不固定黔夭,是可變的籍救。選中l(wèi)ine_bottom坟漱,接下來,我們看下圖:
如下3種模式:
顯然我們要把它切換為AnySize撵溃。
再讓line_bottom下方與橫向line距離為0dp,完成約束锥累,如下圖:
最后我們只剩下一個橫線line缘挑,沒有設(shè)置約束了,一樣他也是可變的桶略,設(shè)置為AnySize语淘,添加約束。如圖:
完成了么际歼?
看起來好像沒有問題了惶翻。不過我們是不是忘了第一個TextView內(nèi)容很多,可能會出現(xiàn)幾行的情況鹅心。
這里我們還需要給第一個TextView的右邊設(shè)置一個到屏幕右邊沿的約束维贺,我們設(shè)置為距離右邊50dp,同時TextView的寬也要設(shè)置為AnySize巴帮,因為他是可變的。
最后所有約束設(shè)置完成虐秋,我們看一下完整版的圖:
我們可以試驗一下是否可以自動適應(yīng)高度榕茧。我們向第一個TextView中寫入一段話,將控件撐大點客给,效果如下圖:
可以看到效果很不錯用押。到此為止,解決問題靶剑,同時ConstraintLayout可以完成很復(fù)雜的布局蜻拨,減少布局的層次,Android布局層次越深桩引,帶來的性能損耗越大缎讼,當(dāng)然對于目前Android手機性能不是問題,但是作為一個進(jìn)益求精的開發(fā)者坑匠,誰不希望用最少的資源血崭,完成最酷的效果呢?