xml 布局文件看似好寫赖歌,也的確好枉圃,但是大家總是百思不得其解,為啥我寫的頁面顯示慢俏站,效率低讯蒲,擴(kuò)展麻煩,有的手機(jī)會(huì)出兼容問題肄扎!這都是大家平時(shí)積累不夠的鍋啊墨林,xml布局文件的書寫是有規(guī)范的,你寫得差一點(diǎn)有的手機(jī)的確沒事犯祠,但是這并不代表所有都是如此旭等,我本人就碰到過使用相對(duì)布局不規(guī)范,出現(xiàn)的兼容問題衡载。還有一兩層布局嵌套就能解決的問題搔耕,為啥還有人寫嵌套寫到讓人奔潰呢,善用 xml痰娱,寫好 xml弃榨,可是看一個(gè) android 開發(fā)技術(shù)功底的事,這里記錄一些我個(gè)人看到的梨睁,總結(jié)的小技巧鲸睛。
目錄導(dǎo)航
- 靈活使用 linearlayout 布局的權(quán)重
- textview 最大行數(shù),固定顯示幾行坡贺,下劃線官辈,刪除線
- 相對(duì)布局規(guī)范:能確定位置的,被依賴的控件寫在前面
- EditView的自定義樣式:光標(biāo)遍坟,下劃線拳亿,選中圖標(biāo),選中文字顏色
- Scrollbar自定義樣式
- clipChildren屬性的使用:允許子View超出父View
- 點(diǎn)九圖(.9.png)的使用
- 使用 tools:attribute 屬性在 xml 中查看效果
- 快速生成 style 樣式
靈活使用 linearlayout 布局的權(quán)重
- 將一個(gè)Button在一行中居中愿伴,并且Button的寬度占屏幕寬度的一半
解決方案:先看具體的xml肺魁,如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#708069"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:weightSum="1" >
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="測(cè)試按鈕" />
</LinearLayout>
其中LinearLayout的android:gravity="center_horizontal"作用是讓Button水平居中;LinearLayout的android:weightSum="1",Button設(shè)置android:layout_weight="0.5"隔节,則表示button占據(jù)父布局即LinearLayout一半的寬度万搔,而LinearLayout為match_parent,因此Button會(huì)占據(jù)屏幕一半的寬度官帘。
- 最外層是LinearLayout,里面水平從左到右放TextView A昧谊,TextView B和一個(gè)Button C,要求A居左刽虹,C居右,B緊靠A呢诬,且單行顯示涌哲,如果文字過多則打點(diǎn)胖缤。
解決方案:為A設(shè)置android:layout_width="wrap_content",為C設(shè)置 android:layout_width="wrap_content"阀圾,且 android:gravity="right|center_vertical"哪廓,為B設(shè)置android:layout_width="0dp",android:layout_weight="1"和android:singleLine="true"初烘。 很容易理解涡真,A在左邊,C在右邊肾筐,然后B利用權(quán)重占據(jù)剩余的水平空間哆料,由于設(shè)置了singleLine,因此文字如果超過一行就會(huì)打點(diǎn)。
-
實(shí)現(xiàn)下圖的效果
解決方案:
(1)左右分別為TextView和ImageView(當(dāng)然使用Button也可以吗铐,這不是重點(diǎn))东亦,外層包一個(gè)水平的LinearLayout。使用shape為TextView和Button分別設(shè)置帶圓角(左邊的shape設(shè)置左上和左下圓角唬渗,右邊的shape設(shè)置右上和右下圓角)和藍(lán)色邊框的背景典阵。這樣做的問題是TextView的右邊框和Button的左邊框都會(huì)存在,導(dǎo)致中間的線會(huì)是正常邊框的兩倍镊逝。因?yàn)閟hape不支持隱藏某一邊的邊框壮啊,因此只能另想他法,我采用了將右邊Button左移動(dòng)1dp(邊框的寬度為1dp蹋半,或者TextView右移1dp),這樣中間的兩個(gè)線條就會(huì)重合他巨,基本可以實(shí)現(xiàn)如圖效果,但也有瑕疵减江,細(xì)看的話染突,中間的豎線由于是兩條線的重合效果,會(huì)顯得比邊框亮一些辈灼。
(2)為外層LinearLayout設(shè)置帶四個(gè)圓角和顏色的邊框份企,LiearLayout里面水平放置2個(gè)控件,左邊TextView巡莹,中間一個(gè)豎線View(width=1dp,跟邊框相同寬度司志,高度為match_parent,顏色為邊框顏色),右邊是Button,然后再給TextView和Button設(shè)置shape背景降宅,與方法(1)不同的是不要設(shè)置實(shí)體邊框骂远,因?yàn)長inearLayout已經(jīng)設(shè)置了邊框。這樣實(shí)現(xiàn)的效果就比較完美了腰根。值得注意的是需要給LinearLayout設(shè)置一個(gè)邊框?qū)挾却笮〉膒adding激才,不然TextView和Button的默認(rèn)顏色會(huì)覆蓋掉LinearLayout邊框的顏色,導(dǎo)致看不到外層邊框。
textview 最大行數(shù)瘸恼,固定顯示幾行劣挫,下劃線,刪除線
- TextView文本最多顯示兩行东帅,多則在末尾打點(diǎn)顯示压固。
解決方案:為TextView添加如下屬性:
android:maxLines="2"
android:ellipsize="end"
第一個(gè)屬性表示該TextView最多可顯示兩行。第二個(gè)屬性設(shè)為end,表示將會(huì)在末尾打點(diǎn)靠闭,還可以設(shè)為其他屬性帐我,如start、middle阎毅、none等焚刚,根據(jù)名字很容易就能理解了。
注意有一個(gè)android:ellipsize="marquee"扇调,即傳說中的跑馬燈效果矿咕,
若要讓TextView里的文本滾動(dòng),必須滿足以下幾個(gè)因素:
(1)TextView里文本寬度超過TextView的寬度,一般需設(shè)置android:singleLine="true"
(2)android:ellipsize="marquee"
(3)只有在TextView獲取到焦點(diǎn)時(shí),才會(huì)滾動(dòng).所以加上android:focusableInTouchMode="true"
android:focusable="true"
滾動(dòng)重復(fù)次數(shù)設(shè)置:
android:marqueeRepeatLimit="marquee_forever"
注意:有時(shí)候設(shè)置了android:maxLines="2"狼钮,而文字只有一行的時(shí)候碳柱,會(huì)導(dǎo)致TextView跟有兩行文字時(shí)高度不一致,因此常常同時(shí)設(shè)置
android:lines="2"熬芜,強(qiáng)制占據(jù)兩行的高度莲镣。
- 需求:給文字設(shè)置下劃線、中劃線
解決方案:如下代碼分別設(shè)置了下劃線和中劃線
textView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG );
textView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
注意涎拉,所生成的線的顏色跟TextView文字的顏色是一致的瑞侮,如果想把文字和下劃線分別設(shè)為不同的顏色,貌似沒有發(fā)現(xiàn)TextView有現(xiàn)成的方法或?qū)傩灾С止呐。覀兛梢圆捎闷渌呗詫?shí)現(xiàn)半火,如文字和下劃線使用兩個(gè)不同的view來實(shí)現(xiàn)。
相對(duì)布局規(guī)范:能確定位置的季俩,被依賴的控件寫在前面
先來看一個(gè)布局
[圖片上傳失敗...(image-75d901-1518453662209)]
這個(gè)布局的特點(diǎn)是按鈕3底部對(duì)齊钮糖,按鈕2在按鈕3的上面,文本框水平充滿剩余的區(qū)域酌住,按鈕1頂部對(duì)齊店归,列表框垂直充滿剩余的區(qū)域。
下面我們會(huì)拆分為下面兩個(gè)子問題:
水平充滿剩余區(qū)域的問題:
水平方向上有兩個(gè)組件酪我,一個(gè)組件寬度為wrap_content(或者固定寬度)消痛,另外一個(gè)組件的需要充滿剩余的寬度,效果如下:
[圖片上傳失敗...(image-527c18-1518453662210)]
左側(cè)一個(gè)文本框都哭,右側(cè)一個(gè)按鈕
如果是嵌套一個(gè)LinearLayout布局肯定就十分簡(jiǎn)單了肄满,如果用RelativeLayout也是可以的谴古,如下:
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/btn3"
android:layout_alignParentRight="true"
android:text="按鈕2"
/>
<EditText
android:id="@+id/et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/btn2"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/btn2"
/>
主要方法如下:(主要通過toRightOf和toLeftOf兩個(gè)屬性)
- 兩個(gè)組件的布局寬度都是wrap_content(或者固定寬度)
- 左邊的組件alignParentLeft,右邊的組件alignParentRight(如果他們左右分別有一些固定寬度的組件稠歉,就用toRightOf(左側(cè))或者toLeftOf(右側(cè))指定的組件)
- 為了讓左邊的組件緊挨著右邊的組件,也就是拉長左側(cè)的文本框汇陆,設(shè)置toLeftOf="右邊組件的ID" (這里是重點(diǎn))怒炸,這樣,左側(cè)文本框就會(huì)自動(dòng)拉伸至和右側(cè)按鈕緊挨著毡代。
- 當(dāng)然阅羹,最后,兩邊組件要水平對(duì)齊教寂,對(duì)左邊組件用alignBaseline="右邊組件的ID"
- 注意要把右側(cè)按鈕在代碼中放到前面(否則編譯時(shí)找不到對(duì)應(yīng)的id捏鱼,因?yàn)樽髠?cè)EditText布局依賴右側(cè)按鈕)
垂直充滿剩余空間的問題:
垂直方向上有兩個(gè)組件,第一個(gè)組件的高度為wrap_content(或固定高度)酪耕,另外一個(gè)組件的高度需要充滿剩余的高度,效果如前面的ListView:
[圖片上傳失敗...(image-10e696-1518453662210)]
這個(gè)時(shí)候也可以通過RelativeLayout實(shí)現(xiàn)导梆,下面我貼出了整個(gè)布局的代碼(為了更好的說明,我在上面和下面都加了一個(gè)組件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="固定寬度按鈕"/>
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="按鈕3"/>
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/btn3"
android:layout_alignParentRight="true"
android:text="按鈕2"
/>
<EditText
android:id="@+id/et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/btn2"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/btn2"
/>
<ListView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/btn2"
android:layout_below="@id/btn1"
/>
</RelativeLayout>
主要看ListView的布局迂烁,方法如下:
- 讓ListView below=上面的組件
- 讓ListView above=下面的組件
- 注意將ListView依賴的組件都放到ListView的上面
看前面我們給出的完整的布局文件代碼看尼,這里需要說明如下內(nèi)容:
注意組件在代碼中的前后擺放,不然會(huì)編譯報(bào)錯(cuò)(前面一直在說)盟步,方法如下:
需要拉伸的組件放到后面藏斩,然后用另一個(gè)組件來進(jìn)行整體的布局。也就是被依賴位置的都放到前面却盘,那些固定長寬(指的是固定或者wrap_content且不依賴其他組件布局的)或者依賴父容器的組件都放到前面狰域,其他組件放到后面,如前面的按鈕1黄橘,按鈕3兆览,按鈕2都放到了前面,因?yàn)榘粹o2依賴于按鈕3(按鈕2 above 按鈕3)旬陡,所以按鈕2也放到了按鈕3的后面拓颓。 (按鈕1說的是最上面那個(gè)固定高度按鈕)
讓兩個(gè)組件水平中線對(duì)齊的問題:
讓一個(gè)組件和另外一個(gè)組件中線對(duì)齊:讓其中一個(gè)組件足夠高(或者我們知道哪個(gè)組件高度一定是高于頂一個(gè)組件的),然后讓需要對(duì)齊的組件和這個(gè)沒有內(nèi)容的組件上下皆對(duì)齊(alignTop,alignBottom設(shè)置)描孟,然后將第二個(gè)組件的gravity為垂直居中即可驶睦。
如果是有 baseline 屬性的 TextView,Button 這類顯示文本的組件的話匿醒,可以通過 align_Baseline 來進(jìn)行對(duì)齊场航,這里的 baseline指的是文本底部對(duì)其的,就像我們小時(shí)候拿一把尺子廉羔,然后比著尺子寫字那種意思溉痢。
EditView的自定義樣式:光標(biāo),下劃線,選中圖標(biāo)孩饼,選中文字顏色
首先看看默認(rèn)樣式(SdkVersion=23髓削,安卓6.0):
文字選擇操作時(shí):
文字選中時(shí):
1.修改光標(biāo)顏色
修改光標(biāo)的顏色很簡(jiǎn)單,只需要使用android:textCursorDrawable="XXX" 屬性镀娶。
首先我們自定義drawable立膛,cursor.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#9bd435"/> <!--顏色設(shè)置為淺綠色-->
<size android:width="2dp"/>
</shape>
使用:
<EditText
android:layout_width="match_parent"
android:textCursorDrawable="@drawable/cursor"
android:layout_height="50dp" />
效果圖:
2.修改選中圖標(biāo)
這個(gè)圖標(biāo)就是默認(rèn)樣式的2圖與3圖中的墨綠色水滴狀圖標(biāo)。同樣也很簡(jiǎn)單梯码,直接上代碼宝泵。
<EditText
android:layout_width="match_parent"
android:textCursorDrawable="@drawable/cursor"
android:textSelectHandleLeft="@drawable/icon"
android:textSelectHandleRight="@drawable/icon"
android:textSelectHandle="@drawable/icon"
android:layout_height="50dp" />
效果:
是不是還覺得有點(diǎn)別扭,文字的選中顏色與EditView默認(rèn)的下劃線還是墨綠色轩娶,其實(shí)改起來也很簡(jiǎn)單儿奶。加上下面兩行代碼。
android:backgroundTint="#9bd435" <!--下劃線顏色-->
android:textColorHighlight="#9bd435" <!--選中文字背景色-->
最終自定義效果:
使用Material Design主題屬性
首先了解一下Material Design 各個(gè)屬性鳄抒。這里有張?jiān)诰W(wǎng)上找來的圖(感謝)闯捎,此圖一目了然。
那么其實(shí)就簡(jiǎn)單了嘁酿,代碼如下
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#9bd435</item>
<item name="android:colorControlActivated">#9bd435</item>
<item name="android:colorControlNormal">#cccccc</item>
</style>
補(bǔ)充一下:android:colorControlActivated表示EditText隙券、Switch、CheckBox闹司、RadioButton等控件激活時(shí)候的顏色娱仔。android:colorAccent與android:colorControlActivated作用一樣,但是它可以同時(shí)設(shè)置文字選中顏色游桩。android:colorControlNormal表示EditText牲迫、Switch、CheckBox借卧、RadioButton等控件默認(rèn)時(shí)的顏色盹憎。兼容5.0以下必須使用Theme.AppCompat主題(兼容部分效果),并且Activity要繼承AppCompatActivity铐刘,在兼容時(shí)候需要把前面的android:前綴去掉陪每。
效果圖:
我看了下自己手機(jī)中的部分應(yīng)用,發(fā)現(xiàn)使用1镰吵、2方法去自定義的只有UC瀏覽器檩禾,其中微信和淘寶直接使用的默認(rèn)樣式。支付寶使用了3方法疤祭,畢竟簡(jiǎn)單盼产,效果也不錯(cuò)。
Scrollbar自定義樣式
首先看看默認(rèn)樣式(SdkVersion=23勺馆,安卓6.0):
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_height="wrap_content">
......
</ScrollView>
效果圖:
自定義滾動(dòng)條首先我們要自定義drawable戏售,scrollbar.xml自定義代碼:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#9bd435"/>
<corners android:radius="2dp" />
</shape>
使用scrollbarThumbVertical:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:scrollbarSize="4dp"
android:scrollbars="vertical"
android:scrollbarThumbVertical="@drawable/scrollbar"
android:layout_height="wrap_content">
......
</ScrollView>
效果圖:
當(dāng)然水平方向的滾動(dòng)條也是可以自定義的侨核,同時(shí)這些也都適用于ListView、RecyclerView灌灾。
android:scrollbars="horizontal"
android:scrollbarThumbHorizontal="xxx"
最后還有一個(gè)android:scrollbarStyle="xxx"搓译,可以設(shè)置滾動(dòng)條的位置。默認(rèn)是insideOverlay紧卒,下面我直接上相應(yīng)設(shè)置對(duì)應(yīng)的效果圖侥衬。
insideInset:(位置在padding內(nèi),會(huì)插入在View后面跑芳,不會(huì)遮擋View)
outsideOverlay:(位置在padding外,覆蓋在View上直颅,如果滾動(dòng)條比padding大會(huì)遮擋View)
outsideInset:(位置在padding外博个,會(huì)插入在View后面,不會(huì)遮擋View)
最后兩張圖可能乍一看是一樣的功偿,其實(shí)仔細(xì)看button距滾動(dòng)條的位置其實(shí)是不一樣的盆佣。
3.修改滑動(dòng)盡頭陰影顏色
默認(rèn)陰影如圖:(SdkVersion=23,安卓6.0)
修改顏色有一種簡(jiǎn)單方法械荷,使用Material Design主題屬性colorPrimary共耍,代碼效果如下:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#9bd435</item>
</style>
當(dāng)然,如果你想去除陰影也非常簡(jiǎn)單吨瞎,加上android:overScrollMode="never" 屬性即可痹兜。
clipChildren屬性的使用:允許子View超出父View
android:clipChildren的意思是是否允許子View超出父View。好像有點(diǎn)懵颤诀,那我們直接上例子字旭。
圖中是現(xiàn)在大多外賣app都會(huì)有的一個(gè)購物車效果。其中紅框中的部分高度略高于旁邊的View崖叫。那么這時(shí)就可以使用clipChildren來實(shí)現(xiàn)遗淳。首先在布局根節(jié)點(diǎn)設(shè)置android:clipChildren="false",在使用android:layout_gravity="xxx"控制超出部分心傀。
代碼:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"> <!--這里-->
<LinearLayout
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal">
<RelativeLayout
android:layout_gravity="bottom" <--這里
android:layout_marginLeft="10dp"
android:layout_width="48dp"
android:layout_height="60dp">
<ImageView
android:src="@drawable/icon_cart"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_marginTop="6dp"
android:layout_alignParentRight="true"
android:background="@drawable/icon_spot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="1"
android:textSize="12sp"
android:gravity="center"
android:textColor="#ffffff"/>
</RelativeLayout>
<TextView
android:layout_marginLeft="10dp"
android:textColor="#9bd435"
tools:text="¥5.00"
android:textStyle="bold"
android:textSize="18sp"
android:gravity="center_vertical"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:layout_width="110dp"
android:textColor="#ffffff"
android:gravity="center"
android:textSize="16sp"
android:text="去購物車"
android:background="#9bd435"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>
效果圖:
點(diǎn)九圖(.9.png)的使用
接著上面的購物車效果屈暗,在圖中是不是有一個(gè)代表購買商品數(shù)量的數(shù)字。如果此時(shí)一個(gè)土豪一次買了上百份的外賣脂男,上面的效果會(huì)如何养叛?我就試了試,得到了下面的效果:
可以清楚地看到原本的圓形被橫向拉伸了疆液。一铅。。那就說明這個(gè)圓形圖標(biāo)不是點(diǎn)九圖堕油。那么我們來制作張潘飘。
大家使用Studio可以很方便的去制作肮之,首先右鍵圖片,會(huì)彈出以下菜單:
點(diǎn)擊Create 9-Patch file... 創(chuàng)建點(diǎn)九圖片卜录。
上圖就是最終完成的圖片戈擒,在上面我有標(biāo)注各個(gè)位置的含義。
替換圖片后現(xiàn)在再來看看效果:
使用 tools:attribute 屬性在 xml 中查看效果
xml 中的 tools 屬性是一個(gè)測(cè)試用的輔助屬性艰毒,設(shè)置了 tools 的屬性并不會(huì)真是的去給這個(gè)屬性值賦值筐高,而僅僅是用來在 xml 觀察效果的
快速生成 style 樣式
以前我們寫 style 樣式的樣式是一樣一樣復(fù)制過去的,麻煩的要死丑瞧,但是呢 AS 這個(gè) IDE 開發(fā)工具是無比強(qiáng)大的柑土,其實(shí)可以快速生成 style 樣式的。右鍵打開菜單绊汹,依次選擇Refactor -> Extract -> Style 稽屏,下面看我的圖就明白了
我們先正常編寫一個(gè) view ,然后在這個(gè) view 的位置點(diǎn)擊右鍵西乖,然后如上面的操作狐榔,就會(huì)出現(xiàn)一個(gè)生成 style 樣式的確認(rèn)頁,可以選擇相關(guān)的屬性获雕,給 style 命名薄腻。是不是很方面