一个drawable 资源总体上就是一个可以绘制在屏幕上的图形,可以被用来定义外形,颜色,边界,渐变等等,可以在一个活动的view中展示。它代表性的应用于展示在特定的view或context中自定义的view图形,倾向于在XML文件中定义它,然后可以通过java代码或者XML文件应用在view中。
官方文档:https://developer.android.com/guide/topics/resources/drawable-resource.html
使用
Drawable是一个很大的话题,因为在不同的情况下有很多不同的类型比如:绘制形状,设置按钮的状态行为,创造伸缩的按钮背景,创造组建绘制层。
5种最重要的:
1. Shape Drawables-定义一个外形带有例如行程,填充,间距等属性
2. StateList Drawables-定义一个Drawables列表供不同状态使用
3. LayerList Drawables-定义一个drawables group列表形成一个复合的结果
4. NinePatch Drawables-PNG文件带有可伸缩的区域允许伸缩
5. Vector Drawables-基于矢量图定义一个复杂的XML文件
Drawing Shapes
参见:我的另一篇文章
StateList Drawable
定义在XML文件中的对象,使用不同的图片呈现在相同的图形上,取决于对对象的状态,例如一个按钮的状态:按压,焦点,其他,使用状态列表drawable可以为不同的状态提供不同的背景图。属性包括:state_pressed
state_focused
state_enabled
state_selected
state_normal
state_disabled
参见我关于StateList Drawable的博客
Layer List
一个图层是用来管理其它的drawables的,每个drawable会按照list中的顺序绘制最后的会被绘制在最高层,根节点是<layer-list>
元素是<item>
可以在<item>
中设置left,right,top,bottom
属性来控制上一个图层的偏移。
注意点:item项也可以是图片或者其他类型的drawable构建一个复杂的图像
Nine-patch图片
在SDKtools问件夹中找到draw9patch.bat文件
Vector Drawables(矢量图)
是一种XML格式的drawables可以定义复杂的基于矢量的图片,图片可以自动的被缩放成各种密度。因此只需要一个资源文件夹可以应对。
5.0系统前
android studio 1.4为5.0之前的系统提供了兼容支持,通过在编译时候自动生成PNG资源文件但是我们需要首先消除自动生成工具通过使用:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
然后加上库
dependencies {
compile "com.android.support:support-vector-drawable:${supportLibVersion}" // VectorDrawableCompat
compile "com.android.support:animated-vector-drawable:${supportLibVersion}" // AnimatedVectorDrawableCompat
}
导入矢量图:
1. android studio 内置了矢量图可以在res上右键new选择vector asset选项。选择choose可以使用现有的svg
2. 从相关网站上下载有SVG图片然后导入
自定义一个按钮
步骤:
3. 为了可以套用按钮风格我们需要在style文件中自定义一个按钮的风格
我们将背景设置为drawable文件,是一个状态选择器可以在不同状态下展示不同的效果。
<style name = "NiceButton" parent="@android:style/Widget.Button">
<item name="android:gravity">center</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:background">@drawable/states_nice_button</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
</style>
- 然后构建一个状态选择器drawable文件,分为pressed,focused,enabled三种状态,每种指定一个drawable文件
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:state_enabled="true"
android:drawable="#111111"/>
<item android:state_focused="true"
android:state_enabled="true"
android:drawable="@drawable/nice_button_focused"/>
<item android:state_enabled="true"
android:drawable="@drawable/nice_button_enabled"/>
</selector>
- 最后分别创建三种状态shape文件,显示不同的效果。
例如nice_button_pressed
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#0078a5"
android:endColor="#00adee"
android:angle="270"/>
<padding android:left="15dp"
android:top="1dp"
android:right="15dp"
android:bottom="1dp"/>
<stroke android:width="1dp"
android:color="#0076a3"/>
<corners android:radius="8dp"/>
</shape>
自定义ListView
- 首先定义每一项的布局,首先是一个TextView
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="5dp"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
- 在main_activity中新建一个ListView。
<ListView
android:id="@+id/lvTest"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
- 在代码中加载这个布局完成第一步
ArrayList<String> items = new ArrayList<String>();
for (int i = 1; i < 8; i++) {
items.add("Item " + i);
}
ArrayAdapter<String> aItems = new ArrayAdapter<String>(this, R.layout.item_simple, items);
lvTest = (ListView) findViewById(R.id.lvTest);
lvTest.setAdapter(aItems);
- 为每一项设置自定义风格:正常状态下:
gradient_bg.xml
这里使用渐变
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#f1f1f2"
android:centerColor="#e7e7e8"
android:endColor="#cfcfcf"
android:angle="270" />
</shape>
- 然后是点击的风格
gradient_pressed_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#C1E1A6"
android:endColor="#118C4E"
android:angle="270" />
</shape>
- 状态选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="@drawable/gradient_bg" />
<item android:state_pressed="true"
android:drawable="@drawable/gradient_pressed_bg" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="@drawable/gradient_pressed_bg" />
</selector>
- 为lIstView设置一个边界:同名内容的话可以用@null
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<stroke android:width="1dp" android:color="#b5b5b5" />
<solid android:color="#00000000" />
</shape>
- 为TextView设置背景为states_selector_list
- 为listview设置背景为list——border,listView有专门 专门的属性
listSelector
用于状态选择,
divider=
定义每项分割线颜色
dividerHeight
定义每项之间的高度
<ListView
...
android:padding="1dp"
android:divider="#b5b5b5"
android:dividerHeight="1dp"
android:background="@drawable/list_border"
android:listSelector="@drawable/states_selector_list" >
</ListView>
动态设置Drawable
例如给予一个res/drawables/message_bubble.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/outerRectangle">
<shape android:shape="rectangle" >
<solid android:color="#FF00FF" />
</shape>
</item>
<item android:left="10dp">
<shape android:shape="rectangle" >
<solid android:color="#ffccd2" />
</shape>
</item>
</layer-list>
我们可以根据id设置第一项
//根据view得到LayerDrawable对象
LayerDrawable buddle = (LayerDrawable) tvFoo.getBackground();
//进入
GradientDrawable outerRect = (GradientDrawable) buddle.findDrawableByLayerId(R.id.outerRecangle);
//改变填充颜色
outerRect.setColor(Color.parseColor("#2f8f22"));
虽然颜色是solid颜色,但是这里要转换成为GradientDrawable对象