Android-Xml绘图
Android XML繪圖
XMl在Android中可不僅僅是一個布局文件、配置列表。它甚至可以變成一張畫、一張圖。
Bitmap
聲明:
res/drawable/bitmap.xml
引用
<ImageView android:id="@+id/id_iv_zjl"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/bitmap" />Shape
android的樣式主要則是通過shape、selector、layer-list、level-list、style、theme等組合實現。
一般用shape定義的xml文件存放在drawable目錄下,若項目沒有該目錄則新建一個,而不要將它放到drawable-hdpi等目錄中。
使用shape可以自定義形狀,可以定義下面四種類型的形狀,通過android:shape屬性指定:
- rectangle: 矩形,默認的形狀,可以畫出直角矩形、圓角矩形、弧形等
- oval: 橢圓形,用得比較多的是畫正圓
- line: 線形,可以畫實線和虛線
- ring: 環形,可以畫環形進度條
通過shape可以在XML中繪制任何形狀,下面展示了Shape所支持的參數
<shapexmlns:android="http://schemas.android.com/apk/res/android"//默認為rectangleandroid:shape=["rectangle"|"oval"|"line"|"ring"]><corners //當shape="rectangle"時使用//半徑,會被后面的單個半徑屬性覆蓋android:radius="integer"android:topLeftRadius="integer"android:topRightRadius="integer"android:bottomLegtRadius="integer"android:bottomRightRadius="integer"/><gradient //漸變android:angle="integer"android:centerX="integer"android:centerY="integer"android:centerColor="color"android:endColor="color"android:gradientRadius="integer"android:startColor="color"android:type=["linear"|"radial"|"sweep"]android:useCenter=["true"|"false"]/><paddingandroid:left="integer"android:top="integer"android:right="integer"android:bottom="integer"/><size //指定大小,一般用在ImageView配合scaleType屬性使用android:width="integer"android:height="integer"/><solid //填充顏色android:color="color"/><stroke //指定邊框android:width="integer"android:color="color"//虛線寬度android:dashWidth="integer"//虛線間隔寬度android:dashGap="integer"/> </shape>rectangle
solid: 設置形狀填充的顏色,只有android:color一個屬性
android:color 填充的顏色padding: 設置內容與形狀邊界的內間距,可分別設置左右上下的距離
android:left 左內間距 android:right 右內間距 android:top 上內間距 android:bottom 下內間距gradient: 設置形狀的漸變顏色,可以是線性漸變、輻射漸變、掃描性漸變
android:type 漸變的類型linear 線性漸變,默認的漸變類型radial 放射漸變,設置該項時,android:gradientRadius也必須設置sweep 掃描性漸變 android:startColor 漸變開始的顏色 android:endColor 漸變結束的顏色 android:centerColor 漸變中間的顏色 android:angle 漸變的角度,線性漸變時才有效,必須是45的倍數,0表示從左到右,90表示從下到上 android:centerX 漸變中心的相對X坐標,放射漸變時才有效,在0.0到1.0之間,默認為0.5,表示在正中間 android:centerY 漸變中心的相對X坐標,放射漸變時才有效,在0.0到1.0之間,默認為0.5,表示在正中間 android:gradientRadius 漸變的半徑,只有漸變類型為radial時才使用 android:useLevel 如果為true,則可在LevelListDrawable中使用corners: 設置圓角,只適用于rectangle類型,可分別設置四個角不同半徑的圓角,當設置的圓角半徑很大時,比如200dp,就可變成弧形邊了
android:radius 圓角半徑,會被下面每個特定的圓角屬性重寫 android:topLeftRadius 左上角的半徑 android:topRightRadius 右上角的半徑 android:bottomLeftRadius 左下角的半徑 android:bottomRightRadius 右下角的半徑stroke: 設置描邊,可描成實線或虛線。
android:color 描邊的顏色 android:width 描邊的寬度 android:dashWidth 設置虛線時的橫線長度 android:dashGap 設置虛線時的橫線之間的距離<?xml version="1.0" encoding="utf-8"?><!-- android:shape指定形狀類型,默認為rectangle --> <shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!-- solid指定形狀的填充色,只有android:color一個屬性 --><solid android:color="#2F90BD" /><!-- padding設置內容區域離邊界的間距 --><padding android:bottom="12dp"android:left="12dp"android:right="12dp"android:top="12dp" /><!-- corners設置圓角,只適用于rectangle --><corners android:radius="200dp" /><!-- stroke設置描邊 --><stroke android:width="2dp"android:color="@android:color/darker_gray"android:dashGap="4dp"android:dashWidth="4dp" /></shape>
接著在要使用的view里引用就可以了,例如本例中用做TextView的background:
<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="8dp"android:text="加了虛線描邊的矩形"android:textSize="16sp"android:textColor="@android:color/white"android:background="@drawable/bg_rectangle_with_stroke_dash" />效果圖:
全部效果圖:
oval
oval用來畫橢圓,而在實際應用中,更多是畫正圓,比如消息提示,圓形按鈕等
上面的效果圖應用了solid、padding、stroke、gradient、size幾個特性。size是用來設置形狀大小的,如下:
- size: 設置形狀默認的大小,可設置寬度和高度
android:width 寬度
android:height 高度
數字0是默認的橢圓,只加了solid填充顏色,
數字1則加了上下左右4dp的padding,
后面的數字都是正圓,是通過設置size的同樣大小的寬高實現的,也可以通過設置控件的寬高一致大小來實現。
數字3加了描邊,
數字4是鏤空描邊,
數字5是虛線描邊,
數字6用了radial漸變。注意,使用radial漸變時,必須指定漸變的半徑,即android:gradientRadius屬性。
以下是漸變的代碼實現,文件為bg_oval_with_gradient.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><!-- padding設置內間距 --><padding android:bottom="4dp"android:left="4dp"android:right="4dp"android:top="4dp" /><!-- size設置形狀的大小 --><size android:width="40dp"android:height="40dp" /><!-- gradient設置漸變 --><gradient android:endColor="#98FB98"android:gradientRadius="40dp"android:startColor="#D1EEEE"android:type="radial" /></shape>引用的代碼:
<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:layout_margin="8dp"android:text="6"android:textSize="20sp"android:textColor="@android:color/black"android:background="@drawable/bg_oval_with_gradient" />line
line主要用于畫分割線,是通過stroke和size特性組合來實現的,先看虛線的代碼:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="line"><stroke android:width="1dp"android:color="#FF0000" /><!-- 虛線的高度 --><size android:height="4dp" /></shape>畫線時,有幾點特性必須要知道的:
- 只能畫水平線,畫不了豎線;
- 線的高度是通過stroke的android:width屬性設置的;
- size的android:height屬性定義的是整個形狀區域的高度;
- size的height必須大于stroke的width,否則,線無法顯示;
- 線在整個形狀區域中是居中顯示的;
- 線左右兩邊會留有空白間距,線越粗,空白越大;
- 引用虛線的view需要添加屬性android:layerType,值設為”software”,否則顯示不了虛線。
引用:
<ImageView android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:background="@drawable/bg_line_with_solid" />ring
首先,shape根元素有些屬性只適用于ring類型,先過目下這些屬性吧:
- android:innerRadius 內環的半徑
- android:innerRadiusRatio 浮點型,以環的寬度比率來表示內環的半徑,默認為3,表示內環半徑為環的寬度除以3,該值會被 android:innerRadius覆蓋
- android:thickness 環的厚度
- android:thicknessRatio 浮點型,以環的寬度比率來表示環的厚度,默認為9,表示環的厚度為環的寬度除以9,該值會被-android:thickness覆蓋
- android:useLevel 一般為false,否則可能環形無法顯示,只有作為LevelListDrawable使用時才設為true
第一個圖只添加了solid;
第二個圖只添加了gradient,類型為sweep;
第三個圖只添加了stroke;
第四個圖添加了gradient和stroke兩項特性。
以下為第四個圖的代碼:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"android:innerRadiusRatio="3"android:shape="ring"android:thicknessRatio="9"android:useLevel="false"><gradient android:endColor="#2F90BD"android:startColor="#FFFFFF"android:type="sweep" /><stroke android:width="1dp"android:color="@android:color/black" /> </shape>如果想讓這個環形旋轉起來,變成可用的進度條,則只要在shape外層包多一個rotate元素就可以了。
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android"android:fromDegrees="0"android:pivotX="50%"android:pivotY="50%"android:toDegrees="1080.0"><shape android:innerRadiusRatio="3"android:shape="ring"android:thicknessRatio="8"android:useLevel="false"><gradient android:endColor="#FF0000"android:startColor="#FFFFFF"android:type="sweep" /></shape></rotate>引用
android:indeterminateDrawable
Layer
本案例參考剛哥的博客layer-list
向前輩學習~
效果分析:
TAB的背景效果 + 帶陰影的圓角矩形
在這里我們沒有用到任何的圖片,完全是依靠 shape+selector+layer-list完成。
使用layer-list可以將多個drawable按照順序層疊在一起顯示,像上圖中的Tab,是由一個紅色的層加一個白色的層疊在一起顯示的結果,陰影的圓角矩形則是由一個灰色的圓角矩形疊加上一個白色的圓角矩形。
Tab背景的代碼:
第一種實現方式:
bg_tab_selector.xml
bg_tab_selected.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"><!-- 紅色底 --><item><color android:color="#E4007F" /></item><!-- 白色背景 --><item android:bottom="4dp"android:drawable="@android:color/white" /> </layer-list>bg_tab_unselected.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"><!-- 紅色底 --><item><color android:color="#E4007F" /></item><!-- 白色背景 --><item android:bottom="1dp"android:drawable="@android:color/white" /> </layer-list>第二種實現方式 (只是把第一種的實現方式寫到一個文件里)
bg_tab_selected.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"><!-- 第一種加載方式 --><!-- <item android:drawable="@drawable/bg_tab_selected"android:state_checked="true" />>--><!-- <item android:drawable="@drawable/bg_tab_unselected" />--><!-- 第二種加載方式 --><!--選中的時候--><item android:state_checked="true"><layer-list><!-- 紅色底 --><item><color android:color="#E4007F" /></item><!-- 白色背景 --><item android:bottom="4dp" android:drawable="@android:color/white" /></layer-list></item><!--非選中的時候--><item><layer-list><item><color android:color="#E4007F" /></item><item android:bottom="1dp"><color android:color="@android:color/white" /></item></layer-list></item></selector>文本部分:
res/color/text_tab_selector.xml
帶陰影的圓角矩形:
bg_shadow_corners_rectangle.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"android:paddingBottom="16dp"android:paddingMode="stack"android:paddingTop="16dp"><!-- 灰色陰影 --><item android:left="2dp"android:top="4dp"><shape><solid android:color="@android:color/darker_gray" /><corners android:radius="10dp" /></shape></item><!-- 白色前景 --><item android:bottom="4dp"android:right="2dp"><shape><solid android:color="#FFFFFF" /><corners android:radius="10dp" /></shape></item> </layer-list>引用:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#E0EEEE"android:orientation="vertical"><RadioGroup android:layout_width="match_parent"android:layout_height="48dp"android:gravity="center"android:orientation="horizontal"><RadioButton android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/bg_tab_selector"android:button="@null"android:gravity="center"android:text="TAB1"android:textColor="@color/text_tab_selector" /><RadioButton android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/bg_tab_selector"android:button="@null"android:gravity="center"android:text="TAB2"android:textColor="@color/text_tab_selector" /><RadioButton android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"android:background="@drawable/bg_tab_selector"android:button="@null"android:gravity="center"android:text="TAB3"android:textColor="@color/text_tab_selector" /></RadioGroup><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@drawable/bg_shadow_corners_rectangle"android:gravity="center"android:padding="16dp"android:text="帶陰影的圓角矩形-1" /><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@drawable/bg_shadow_corners_rectangle"android:gravity="center"android:padding="16dp"android:text="帶陰影的圓角矩形-2" /> </LinearLayout>總結:
- 從上面的示例代碼可以看到,layer-list可以作為根節點,也可以作為selector中item的子節點。
- layer-list可以添加多個item子節點,每個item子節點對應一個drawable資源,按照item從上到下的順序疊加在一起,再通過設置每個item的偏移量就可以看到陰影等效果了
- layer-list的item可以通過下面四個屬性設置偏移量:
android:top 頂部的偏移量
android:bottom 底部的偏移量
android:left 左邊的偏移量
android:right 右邊的偏移量
- 這四個偏移量和控件的margin設置差不多,都是外間距的效果。如何不設置偏移量,前面的圖層就完全擋住了后面的圖層,從而也看不到后面的圖層效果了。比如上面的例子,Tab背景中的白色背景設置了android:bottom之后才能看到一點紅色背景。那么如果偏移量設為負值會怎么樣呢?經過驗證,偏移超出的部分會被截掉而看不到,不信可以自己試一下。有時候這很有用,比如當我想顯示一個半圓的時候。
另外,關于item的用法,也做下總結:
- 根節點不同時,可設置的屬性是會不同的,比如selector下,可以設置一些狀態屬性,而在layer-list下,可以設置偏移量;
- 就算父節點同樣是selector,放在drawable目錄和放在color目錄下可用的屬性也會不同,比如drawable目錄下可用的屬性為android:drawable,在color目錄下可用的屬性為android:color;
- item的子節點可以為任何類型的drawable類標簽,除了上面例子中的shape、color、layer-list,也可以是selector,還有其他沒講過的bitmap、clip、scale、inset、transition、rotate、animated-rotate、lever-list等等。
Selector
之前的博文底部導航欄的幾種實現方式底部是采用了selector樣式,也可以看下。
先看下最后的實現效果:
下面切入正題:
shape雖然可以自定義矩形、圓形、線形和環形,以及有哪些需要注意的地方。不過,shape只能定義單一的形狀,而實際應用中,很多地方比如按鈕、Tab、ListItem等都是不同狀態有不同的展示形狀。舉個例子,一個按鈕的背景,默認時是一個形狀,按下時是一個形狀,不可操作時又是另一個形狀。有時候,不同狀態下改變的不只是背景、圖片等,文字顏色也會相應改變。而要處理這些不同狀態下展示什么的問題,就要用selector來實現了。
selector標簽,可以添加一個或多個item子標簽,而相應的狀態是在item標簽中定義的。
定義的xml文件可以作為兩種資源使用:drawable和color。
作為drawable資源使用時,一般和shape一樣放于drawable目錄下,item必須指定android:drawable屬性;
作為color資源使用時,則放于color目錄下,item必須指定android:color屬性。
可設置的狀態:
如果不愿意手工編寫,可以在Android Studio使用插件android-selector-chapek,但是圖片的命名規則需要按照規范才可以自動生成。
注意事項:
- selector作為drawable資源時,item指定android:drawable屬性,并放于drawable目錄下;
- selector作為color資源時,item指定android:color屬性,并放于color目錄下;
- color資源也可以放于drawable目錄,引用時則用@drawable來引用,但不推薦這么做,drawable資源和color資源最好還是分開;
android:drawable屬性除了引用@drawable資源,也可以引用@color顏色值;但android:color只能引用@color; - item是從上往下匹配的,如果匹配到一個item那它就將采用這個item,而不是采用最佳匹配的規則;所以設置默認的狀態,一定要寫在最后,如果寫在前面,則后面所有的item都不會起作用了。
另外,selector標簽下有兩個比較有用的屬性要說一下,添加了下面兩個屬性之后,則會在狀態改變時出現淡入淡出效果,但必須在API Level 11及以上才支持:
android:enterFadeDuration 狀態改變時,新狀態展示時的淡入時間,以毫秒為單位
android:exitFadeDuration 狀態改變時,舊狀態消失時的淡出時間,以毫秒為單位
最后,關于ListView的ListItem樣式,有兩種設置方式,一種是在ListView標簽里設置android:listSelector屬性,另一種是在ListItem的布局layout里設置android:background。
但是,這兩種設置的結果卻有著不同。同時,使用ListView時也有些其他需要注意的地方,總結如下:
- android:listSelector設置的ListItem默認背景是透明的,不管你在selector里怎么設置都無法改變它的背景。所以,如果想改ListItem的默認背景,只能通過第二種方式,在ListItem的布局layout里設置android:background。
- 當觸摸點擊ListItem時,第一種設置方式下,state_pressed、state_focused和state_window_focused設為true時都會觸發,而第二種設置方式下,只有state_pressed會觸發。
當ListItem里有Button或CheckBox之類的控件時,會搶占ListItem本身的焦點,導致ListItem本身的觸摸點擊事件會無效。那么,要解決此問題,有三種解決方案:
將Button或CheckBox換成TextView或ImageView之類的控件
- 設置Button或CheckBox之類的控件設置focusable屬性為false
設置ListItem的根布局屬性- android:descendantFocusability=”blocksDescendants”
第三種是最方便,也是推薦的方式,它會將ListItem根布局下的所有子控件都設置為不能獲取焦點。android:descendantFocusability屬性的值有三種,其中,ViewGroup是指設置該屬性的View,本例中就是ListItem的根布局:
- beforeDescendants:ViewGroup會優先其子類控件而獲取到焦點
- afterDescendants:ViewGroup只有當其子類控件不需要獲取焦點時才獲取焦點
- blocksDescendants:ViewGroup會覆蓋子類控件而直接獲得焦點
shape layer-list selector中的內容學習自Keegan小鋼的文章,感謝前輩 受益匪淺~
總結
以上是生活随笔為你收集整理的Android-Xml绘图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Studio报Eleme
- 下一篇: 干货一:通过自定义PopupWindow