今天为了适配启动页背景图,接触到了BitmapDrawable保证了启动页的背景图不变形。想想之前真的没用过,所以还是有必要详细了解一下Drawable,至少在遇到一些问题时可以及时的找到解决方案。
Drawable的分类
Drawable一般都是用XML定义的,但是我们也可以自定义Drawable,但是代码会比较复杂。
BitmapDrawablw
可以理解为它是一张带规则的图片,一般情况下如果可以在ImageView里面设置属性的就没必要使用,但是如果一张图片要做到像放在控件里适配就有必要使用了,例如启动页背景图
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="clip_horizontal|clip_vertical"
android:dither="true"
android:src="@drawable/splash_bg"
android:tileMode="disabled"/>
<!--属性解释-->
<!--android:src 图片资源id-->
<!--android:antialias是否开启抗锯齿,应该开启-->
<!--android:dither是否开启抖动效果,应该开启-->
<!--android:filter是否开启过滤效果,应该开启-->
<!--android:gravity对图片进行定位-->
<!--android:mipMap纹理映射,一般为false-->
<!--android:tileMode平铺模式四个值:disabled(默认值即关闭平铺模式)、clamp、repeat、mirror-->
如果直接使用图片,由于不能控制图片的位置,有些手机会变形很严重。
NinePatchDrawable
与BitmapDrawable类似不过NinePatchDrawable的效果类似于.9图,实际使用时其实直接使用.9图就好
ShapeDrawable
开发时用的比较多,可以理解为只有纯颜色或渐变色的图片。只是有些地方需要注意一下。
以上代码是一个指定渐变百分比的渐变shape,其中centerY与centerColor必须同时设置才能生效,否则只是普通的渐变,另外,其实我们的系统进度条也可以设置渐变
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:max="1000"
android:progress="0"
android:progressDrawable="@drawable/progress_green" />
<?xml version="1.0" encoding="utf-8"?>
<!--progress_green-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="50dp" />
<solid android:color="@android:color/transparent" />
</shape>
</item>
<item android:id="@android:id/progress">
<scale
android:drawable="@drawable/progress_shape"
android:scaleWidth="100%" />
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<!--progress_shape-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="@color/theme_color"
android:startColor="@color/theme_color1"
android:type="linear" />
</shape>
进度条max的值由于没有小数,所以设置1000效果会好很多,加上动画效果后效果如下
LayerDrawable
对应的标签是layer-list,表示一种层次化的Drawable。很多时候都可以使用布局嵌套完成,但是使用layor-list可以减少布局的层级结构,例如
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke android:width="1dp" android:color="#45DAA8" />
</shape>
</item>
<item>
<bitmap android:src="@drawable/gou"
android:gravity="bottom|right" />
</item>
</layer-list>
效果图
StateListDrawble
这个开发中也经常用到,标签对应的是selector。比如我们的点击效果、还有选择后与选择前的不同效果,使用selector可以在代码中设置一个属性改变很方便。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/bg_btn_circle_gradient_full">
</item>
<item android:state_enabled="false">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#aaffffff">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:radius="360dp" />
<solid
android:color="@color/gray_eeeeee"
/>
</shape>
</item>
</ripple>
</item>
</selector>
这里结合了ripple标签,可以做出水波纹效果。效果如下
LevelListDrawable
也是一个Drawable的集合,对应的标签是level-list。有点类似于layer-list,不过level-list是根据等级(0~10000)来显示的,而layer-list则是显示在一起的。开发中比较少用到,如果一个按钮有多种状态可以考虑使用代替if-else判断显示
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_heat" android:maxLevel="1"/>
<item android:drawable="@drawable/icon_cool" android:maxLevel="2"/>
</level-list>
imageview.getDrawable().setLevel(1);
TransitionDrawable
可以实现两个Drawable之间的淡入淡出,对应的标签是transition。
##ScaleDrawable
对应的标签是scale,可以根据level指定Drawable缩放到一定比例。
这两个效果我觉得可以在启动页的背景图做一点动画效果或者做全局的动画,其他地方可以使用动画代替。
InsetDrawable
对应的标签是inset,可以把Drawable内嵌进来,可以用于加大点击区域。
ClipDrawable
对应的标签是clip,可以根据level裁剪出另外一个drawabl。挺有用的一个Drawable可以看看下面的博客 效果图:
自定义Drawable
其实Drawable是一个抽象的概念,可以理解为Canvas之前的一个封装。就是把资源封装成Drawable再绘制到画布上。Drawable可以说是内存级的画布。
过程与自定义View时的绘画是相似的,
读者福利
Android架构师的门槛,有没有免费学习资料?