更多Android總結知識點
本節前言
講本節之前先講一下Drawable xml的布局,為什么要先講這個呢,因為我發現后面講解Ui很多布局里面是要用到這個的,怕大家看不懂,所以我們今天就先講一下Drawable的知識點
Android中給我們提供了多達13種的 Drawable,本節我們就來一個個擼一遍!
Drawable資源使用注意事項
(1)Drawable分為兩種: 一種是我們普通的圖片資源,在Android Studio中我們一般放到res/mipmap目錄下, 和以前的Eclipse不一樣哦!另外我們如果把工程切換成Android項目模式,我們直接 往mipmap目錄下丟圖片即可,AS會自動分hdpi,xhdpi...! 另一種是我們編寫的XML形式的Drawable資源,我們一般把他們放到res/drawable目錄 下,比如最常見的按鈕點擊背景切換的Selctor!
(2)在XML我們直接通過@mipmap或者@drawable設置Drawable即可 比如: android:background = "@mipmap/iv_icon_zhu" / "@drawable/btn_back_selctor" 而在Java代碼中我們可以通過Resource的getDrawable(R.mipmap.xxx)可以獲得drawable資源 如果是為某個控件設置背景,比如ImageView,我們可以直接調用控件.getDrawale()同樣 可以獲得drawable對象!
(3)Android中drawable中的資源名稱有約束,必須是:[a-z0-9_.](即:只能是字母數字及和.), 而且不能以數字開頭,否則編譯會報錯: Invalid file name: must contain only [a-z0-9.]! 小寫啊!!!!小寫!!!小寫!——重要事情說三遍~
好的,要注意的地方大概就這些,下面我們來對Android中給我們提供的13種Drawable進行學習!
1.ColorDrawable
最簡單的一種Drawable,當我們將ColorDrawable繪制到Canvas(畫布)上的時候, 會使用一種固定的顏色來填充Paint,然后在畫布上繪制出一片單色區域!
1).Java中定義ColorDrawable:
ColorDrawable drawable = new ColorDrawable(0xffff2200);
txtShow.setBackground(drawable);
2).在xml中定義ColorDrawable:
<?xml version="1.0" encoding="utf-8"?>
<color
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#FF0000"/>
當然上面這些用法,其實用得不多,更多的時候我們是在res/values目錄下創建一個color.xml 文件,然后把要用到的顏色值寫到里面,需要的時候通過@color獲得相應的值,比如:
3).建立一個color.xml文件
比如:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="material_grey_100">#fff5f5f5</color>
<color name="material_grey_300">#ffe0e0e0</color>
<color name="material_grey_50">#fffafafa</color>
<color name="material_grey_600">#ff757575</color>
<color name="material_grey_800">#ff424242</color>
<color name="material_grey_850">#ff303030</color>
<color name="material_grey_900">#ff212121</color>
</resources>
然后如果是在xml文件中話我們可以通過@color/xxx獲得對應的color值 如果是在Java中:
int mycolor = getResources().getColor(R.color.mycolor);
btn.setBackgroundColor(mycolor);
ps:另外有一點要注意,如果我們在Java中直接定義顏色值的話,要加上0x,而且不能把透明度漏掉:
int mycolor = 0xff123456;
btn.setBackgroundColor(mycolor);
2.NiewPatchDrawable(這里介紹一下,理解一下就可以了)
顧名思義就是.9圖片了,Android FrameWork在顯示點九圖時使用了高效的 圖形優化算法,我們不需要特殊的處理,就可以實現圖片拉伸的自適應~ 另外在使用AS的時候要注意以下幾點:
點9圖不能放在mipmap目錄下,而需要放在drawable目錄下!
3.ShapeDrawable
形狀的Drawable咯,定義基本的幾何圖形,如(矩形,圓形,線條等),根元素是<shape../> 節點比較多,相關的節點如下:
① <shape>:
visible[?v?z?bl]:設置是否可見
shape:形狀,可選:rectangle['rekt??g(?)] (矩形,包括正方形),oval(橢圓,包括圓),line(線段),ring(環形)
innerRadiusRatio:當shape為ring才有效,表示環內半徑所占半徑的比率,如果設置了innerRadius, 他會被忽略
innerRadius:當shape為ring才有效,表示環的內半徑的尺寸
thicknessRatio:當shape為ring才有效,表環厚度占半徑的比率
thickness:當shape為ring才有效,表示環的厚度,即外半徑與內半徑的差
useLevel:當shape為ring才有效,表示是否允許根據level來顯示環的一部分
②<size>:
width:圖形形狀寬度
height:圖形形狀高度
③<gradient>:后面GradientDrawable再講~
④<solid>
color:背景填充色,設置solid后會覆蓋gradient設置的所有效果!!!!!!
⑤<stroke>
width:邊框的寬度
color:邊框的顏色
dashWidth:邊框虛線段的長度
dashGap:邊框的虛線段的間距
⑥<conner>
~ radius:圓角半徑,適用于上下左右四個角
~ topLeftRadius,topRightRadius,BottomLeftRadius,tBottomRightRadius: 依次是左上,右上,左下,右下的圓角值,按自己需要設置!
⑦<padding>
left,top,right,bottm:依次是左上右下方向上的邊距!
使用示例:(后面的TextView會講)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 設置一個黑色邊框 -->
<stroke android:width="2px" android:color="#000000"/>
<!-- 漸變 -->
<gradient
android:angle="270"
android:endColor="#C0C0C0"
android:startColor="#FCD209" />
<!-- 設置一下邊距,讓空間大一點 -->
<padding
android:left="5dp"
android:top="5dp"
android:right="5dp"
android:bottom="5dp"/>
</shape>
4.GradientDrawable
一個具有漸變區域的Drawable,可以實現線性漸變,發散漸變和平鋪漸變效果 核心節點:<gradient/>,有如下可選屬性:
startColor:漸變的起始顏色
centerColor:漸變的中間顏色
endColor:漸變的結束顏色
type:漸變類型,可選(linear,radial,sweep), 線性漸變(可設置漸變角度),發散漸變(中間向四周發散),平鋪漸變
centerX:漸變中間亞瑟的x坐標,取值范圍為:0~1
centerY:漸變中間顏色的Y坐標,取值范圍為:0~1
angle:只有linear類型的漸變才有效,表示漸變角度,必須為45的倍數哦
gradientRadius:只有radial和sweep類型的漸變才有效,radial必須設置,表示漸變效果的半徑
useLevel:判斷是否根據level繪制漸變效果
代碼示例:(三種漸變效果的演示):
運行效果圖:
先在drawable下創建三個漸變xml文件:
(線性漸變)gradient_linear.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:angle="90"
android:centerColor="#FFEB82"
android:endColor="#35B2DE"
android:startColor="#DEACAB" />
<stroke
android:dashGap="5dip"
android:dashWidth="4dip"
android:width="3dip"
android:color="#fff" />
</shape>
(發散漸變)gradient_radial.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dip"
android:shape="ring"
android:thickness="70dip"
android:useLevel="false" >
<gradient
android:centerColor="#FFEB82"
android:endColor="#35B2DE"
android:gradientRadius="70"
android:startColor="#DEACAB"
android:type="radial"
android:useLevel="false" />
</shape>
(平鋪漸變)gradient_sweep.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadiusRatio="8"
android:shape="ring"
android:thicknessRatio="3"
android:useLevel="false" >
<gradient
android:centerColor="#FFEB82"
android:endColor="#35B2DE"
android:startColor="#DEACAB"
android:type="sweep"
android:useLevel="false" />
</shape>
5.BitmapDrawable
對Bitmap的一種封裝,可以設置它包裝的bitmap在BitmapDrawable區域中的繪制方式,有: 平鋪填充,拉伸填或保持圖片原始大小!以<bitmap>為根節點! 可選屬性如下:
src:圖片資源~
antialias['?nti'eili?s]:是否支持抗鋸齒
filter:是否支持位圖過濾,支持的話可以是圖批判顯示時比較光滑
dither:是否對位圖進行抖動處理
gravity:若位圖比容器小,可以設置位圖在容器中的相對位置tileMode:指定圖片平鋪填充容器的模式,設置這個的話,gravity屬性會被忽略,有以下可選值: disabled(整個圖案拉伸平鋪),clamp(原圖大小), repeat(平鋪),mirror(鏡像平鋪)
對應的效果圖:
①XML定義BitmapDrawable:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:src="@drawable/ic_launcher"
android:tileMode="mirror" />
②實現相同效果的Java代碼:
BitmapDrawable bitDrawable = new BitmapDrawable(bitmap);
bitDrawable.setDither(true);
bitDrawable.setTileModeXY(TileMode.MIRROR,TileMode.MIRROR);
6.InsetDrawable
表示把一個Drawable嵌入到另外一個Drawable的內部,并且在內部留一些間距, 類似與Drawable的padding屬性,但padding表示的是Drawable的內容與Drawable本身的邊距! 而InsetDrawable表示的是兩個Drawable與容器之間的邊距,當控件需要的背景比實際的邊框 小的時候,比較適合使用InsetDrawable,比如使用這個可以解決我們自定義Dialog與屏幕之間 的一個間距問題,相信做過的朋友都知道,即使我們設置了layout_margin的話也是沒用的,這個 時候就可以用到這個InsetDrawable了!只需為InsetDrawable設置一個insetXxx設置不同 方向的邊距,然后為設置為Dialog的背景即可!
相關屬性如下:
- 1.drawable:引用的Drawable,如果為空,必須有一個Drawable類型的子節點!
- 2.visible:設置Drawable是否額空間
- 3.insetLeft,insetRight,insetTop,insetBottm:設置左右上下的邊距
①XML中使用:
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/test1"
android:insetBottom="10dp"
android:insetLeft="10dp"
android:insetRight="10dp"
android:insetTop="10dp" />
在Java代碼中使用:
InsetDrawable insetDrawable = new InsetDrawable(getResources() .getDrawable(R.drawable.test1), 10, 10, 10, 10);
使用效果圖:
7.ClipDrawable
Clip [kl?p]可以譯為剪的意思,我們可以把ClipDrawable理解為從位圖上剪下一個部分; Android中的進度條就是使用ClipDrawable來實現的,他根據設置level的值來決定剪切 區域的大小,根節點是<clip>
相關屬性如下:
- clipOrietntion:設置剪切的方向,可以設置水平和豎直2個方向
- gravity:從那個位置開始裁剪
- drawable:引用的drawable資源,為空的話需要有一個Drawable類型的子節點 ps:這個Drawable類型的子節點:就是在<clip里>加上這樣的語句: 這樣...
使用示例:
核心:通過代碼修改ClipDrawable的level的值!Level的值是0~10000!
運行效果圖:
代碼實現:
①定義一個ClipDrawable的資源xml:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal"
android:drawable="@mipmap/ic_bg_meizi"
android:gravity="left" />
②在activity_main主布局文件中設置一個ImageView,將src設置為clipDrawable! 記住是src哦,如果你寫成了blackground的話可是會報空指針的哦!!!!
<LinearLayout 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:orientation="vertical">
<ImageView
android:id="@+id/img_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/clip_bg" />
</LinearLayout>
③MainActivity.java通過setLevel設置截取區域大小:
public class MainActivity extends AppCompatActivity {
private ImageView img_show;
private ClipDrawable cd;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
cd.setLevel(cd.getLevel() + 500);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_show = (ImageView) findViewById(R.id.img_show);
// 核心實現代碼
cd = (ClipDrawable) img_show.getDrawable();
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
if (cd.getLevel() >= 10000) {
timer.cancel();
}
}
}, 0, 300);
}
}
8.RotateDrawable
用來對Drawable進行旋轉,也是通過setLevel來控制旋轉的,最大值也是:10000
相關屬性如下:
fromDegrees:起始的角度,,對應最低的level值,默認為0
toDegrees:結束角度,對應最高的level值,默認360
pivotX:設置參照點的x坐標,取值為0~1,默認是50%,即0.5
pivotY:設置參照點的Y坐標,取值為0~1,默認是50%,即0.5 ps:如果出現旋轉圖片顯示不完全的話可以修改上述兩個值解決!
drawable:設置位圖資源
visible:設置drawable是否可見!
角度圖如下:
使用示例:
運行效果圖:
代碼實現:
在第三點的clipDrawable上做一點點修改即可!
①定義一個rotateDrawable資源文件:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@mipmap/ic_launcher"
android:fromDegrees="-180"
android:pivotX="50%"
android:pivotY="50%" />
②activity_main.xml中修改下src指向上述drawable即可,MainActivity只需要把ClipDrawable 改成rotateDrawable即可!
public class MainActivity extends AppCompatActivity {
private ImageView img_show;
private RotateDrawable cd;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
if (cd.getLevel() >= 10000)
Toast.makeText(MainActivity.this, "轉完了~",
Toast.LENGTH_LONG).show();
cd.setLevel(cd.getLevel() + 400);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_show = (ImageView) findViewById(R.id.img_show);
// 核心實現代碼
cd = (RotateDrawable) img_show.getDrawable();
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
if (cd.getLevel() >= 10000) {
timer.cancel();
}
}
}, 0, 100);
}
}
9.AnimationDrawable(此篇會在后面詳細介紹)
AnimationDrawable是用來實現Android中幀動畫的,就是把一系列的 Drawable,按照一定得順序一幀幀地播放;Android中動畫比較豐富,有傳統補間動畫,平移, 縮放等等效果,但是這里我們僅僅介紹這個AnimationDrawable實現幀動畫,關于alpha,scale, translate,rotate等,后續在動畫章節再進行詳細的介紹~
我們這里使用<animation-list>作為根節點
相關屬性方法:
oneshot:設置是否循環播放,false為循環播放!!!
duration:幀間隔時間,通常我們會設置為300毫秒
我們獲得AniamtionDrawable實例后,需要調用它的start()方法播放動畫,另外要注意 在OnCreate()方法中調用的話,是沒有任何效果的,因為View還沒完成初始化,我們可以 用簡單的handler來延遲播放動畫!當然還有其他的方法
10.LayerDrawable
層圖形對象,包含一個Drawable數組,然后按照數組對應的順序來繪制他們,索引 值最大的Drawable會被繪制在最上層!雖然這些Drawable會有交叉或者重疊的區域,但 他們位于不同的層,所以并不會相互影響,以<layer-list>作為根節點!
相關屬性如下:
drawable:引用的位圖資源,如果為空需要有一個Drawable類型的子節點
left:層相對于容器的左邊距
right:層相對于容器的右邊距
top:層相對于容器的上邊距
bottom:層相對于容器的下邊距
id:層的id
使用示例:
運行效果圖:
代碼實現:
非常簡單,結合前面學習的shapeDrawable和ClipDrawable:
layerList_one.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="#C2C2C1" />
<corners android:radius="50dp" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape android:shape="rectangle">
<solid android:color="#BCDA73" />
<corners android:radius="50dp" />
</shape>
</clip>
</item>
</layer-list>
然后在布局文件中添加一個Seekbar,內容如下:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal"
android:indeterminateOnly="false"
android:maxHeight="10dp"
android:minHeight="5dp"
android:progressDrawable="@drawable/layerlist_one"
android:thumb="@drawable/shape_slider" />
我們還可以弄個層疊圖片的效果:
運行效果圖:
實現代碼:
層疊圖片的layerlist_two.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/ic_bg_ciwei" />
</item>
<item
android:left="25dp"
android:top="25dp">
<bitmap
android:gravity="center"
android:src="@mipmap/ic_bg_ciwei" />
</item>
<item
android:left="50dp"
android:top="50dp">
<bitmap
android:gravity="center"
android:src="@mipmap/ic_bg_ciwei" />
</item>
</layer-list>
然后在activity_main.xml里加個ImageView,內容如下:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/layerlist_two"/>
11.TransitionDrawable
LayerDrawable的一個子類,TransitionDrawable只管理兩層的Drawable!兩層!兩層! 并且提供了透明度變化的動畫,可以控制一層Drawable過度到另一層Drawable的動畫效果。 根節點為<transition>,記住只有兩個Item,多了也沒用,屬性和LayerDrawable差不多, 我們需要調用startTransition方法才能啟動兩層間的切換動畫; 也可以調用reverseTransition()方法反過來播放:
使用示例:
運行效果圖:
實現代碼:
在res/drawable創建一個TransitionDrawable的xml文件
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@mipmap/ic_bg_meizi1"/>
<item android:drawable="@mipmap/ic_bg_meizi2"/>
</transition>
然后布局文件里加個ImageView,然后把src設置成上面的這個drawable 然后MainActivity.java內容如下:
public class MainActivity extends AppCompatActivity {
private ImageView img_show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_show = (ImageView) findViewById(R.id.img_show);
TransitionDrawable td = (TransitionDrawable) img_show.getDrawable();
td.startTransition(3000);
//你可以可以反過來播放,使用reverseTransition即可~
//td.reverseTransition(3000);
}
}
12.LevelListDrawable
用來管理一組Drawable的,我們可以為里面的drawable設置不同的level, 當他們繪制的時候,會根據level屬性值獲取對應的drawable繪制到畫布上,根節點 為:<level-list>他并沒有可以設置的屬性,我們能做的只是設置每個<item> 的屬性!
item可供設置的屬性如下:
drawable:引用的位圖資源,如果為空 需要有一個Drawable類型的子節點
minlevel:level對應的最小值
maxlevel:level對應的最大值
使用示例:
運行效果圖:
代碼實現:
通過shapeDrawable畫圓,一式五份,改下寬高即可:
shape_cir1.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#2C96ED"/>
<size android:height="20dp" android:width="20dp"/>
</shape>
接著到LevelListDrawable,這里我們設置五層:
level_cir.xml:
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/shape_cir1" android:maxLevel="2000"/>
<item android:drawable="@drawable/shape_cir2" android:maxLevel="4000"/>
<item android:drawable="@drawable/shape_cir3" android:maxLevel="6000"/>
<item android:drawable="@drawable/shape_cir4" android:maxLevel="8000"/>
<item android:drawable="@drawable/shape_cir5" android:maxLevel="10000"/>
</level-list>
最后MainActivity寫如下代碼:
public class MainActivity extends AppCompatActivity {
private ImageView img_show;
private LevelListDrawable ld;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
if (ld.getLevel() > 10000) ld.setLevel(0);
img_show.setImageLevel(ld.getLevel() + 2000);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_show = (ImageView) findViewById(R.id.img_show);
ld = (LevelListDrawable) img_show.getDrawable();
img_show.setImageLevel(0);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
}
}, 0, 100);
}
}
13.StateListDrawable
好了終于迎來了最后一個drawable:StateListDrawable,這個名字看上去模式,其實我們 以前就用到了,還記得為按鈕設置不同狀態的drawable的<selctor>嗎?沒錯,用到的 就是這個StateListDrawable!
可供設置的屬性如下:
drawable:引用的Drawable位圖,我們可以把他放到最前面,就表示組件的正常狀態~
state_focused:是否獲得焦點
state_window_focused:是否獲得窗口焦點
state_enabled:控件是否可用
state_checkable:控件可否被勾選,eg:checkbox
state_checked:控件是否被勾選
state_selected:控件是否被選擇,針對有滾輪的情況
state_pressed:控件是否被按下
state_active:控件是否處于活動狀態,eg:slidingTab
state_single:控件包含多個子控件時,確定是否只顯示一個子控件
state_first:控件包含多個子控件時,確定第一個子控件是否處于顯示狀態
state_middle:控件包含多個子控件時,確定中間一個子控件是否處于顯示狀態
state_last:控件包含多個子控件時,確定最后一個子控件是否處于顯示狀態
使用示例:
那就來寫個簡單的圓角按鈕吧!
運行效果圖:
代碼實現:
那就先通過shapeDrawable來畫兩個圓角矩形,只是顏色不一樣而已:
shape_btn_normal.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#DD788A"/>
<corners android:radius="5dp"/>
<padding android:top="2dp" android:bottom="2dp"/>
</shape>
接著我們來寫個selctor:selctor_btn.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/shape_btn_pressed"/>
<item android:drawable="@drawable/shape_btn_normal"/>
</selector>
然后按鈕設置android:background="@drawable/selctor_btn"就可以了~ 你可以根據自己需求改成矩形或者橢圓,圓形等!