一、 shape
使用shape可以自定义形状,可以定义下面四种类型的形状,通过android:shape属性指定:
① rectangle
实现上面的那些效果,都用到了以下这些特性:
demo:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#2F90BD"/>
<padding
android:bottom="12dp"
android:left="12dp"
android:right="12dp"
android:top="12dp"/>
<corners android:radius="200dp"/>
<stroke
android:width="2dp"
android:color="@android:color/darker_gray"
android:dashGap="4dp"
android:dashWidth="4dp"/>
shape>
② oval
oval用来画椭圆,而在实际应用中,更多是画正圆,比如消息提示,圆形按钮等
上面的效果图应用了solid、padding、stroke、gradient、size几个特性。size是用来设置形状大小的,如下:
数字0是默认的椭圆,只加了solid填充颜色
数字1则加了上下左右4dp的padding
后面的数字都是正圆,是通过设置size的同样大小的宽高实现的,也可以通过设置控件的宽高一致大小来实现。
数字3加了描边,数字4是镂空描边,数字5是虚线描边,数字6用了radial渐变。注意,使用radial渐变时,必须指定渐变的半径,即android:gradientRadius属性。
demo:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<padding
android:bottom="4dp"
android:left="4dp"
android:right="4dp"
android:top="4dp"/>
<size
android:width="40dp"
android:height="40dp"/>
<gradient
android:endColor="#000000"
android:gradientRadius="40dp"
android:startColor="#FFFFFF"
android:type="radial"/>
shape>
③ line
line主要用于画分割线,是通过stroke和size特性组合来实现的
demo:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:width="1dp"
android:color="#2F90BD"
android:dashGap="2dp"
android:dashWidth="4dp" />
<size android:height="4dp" />
shape>
画线时,有几点特性必须要知道的:
④ ring(除此之外还可以使用自定义view 实现下列圆的效果,圆二效果见本段结尾附录)
首先,shape根元素有些属性只适用于ring类型,先过目下这些属性吧:
第一个图只添加了solid;第二个图只添加了gradient,类型为sweep;第三个图只添加了stroke;第四个图添加了gradient和stroke两项特性。
以下为第四个图的代码:
<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元素就可以了。
<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="#2F90BD"
android:startColor="#FFFFFF"
android:type="sweep" />
shape>
rotate>
在ProgressBar引用:
<ProgressBar
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="8dp"
android:indeterminate="false"
android:indeterminateDrawable="@drawable/bg_ring_with_gradient_rotate" />
点击这里下载,第二个圆自定义view demo
二、selector
shape只能定义单一的形状,而实际应用中,很多地方比如按钮、Tab、ListItem等都是不同状态有不同的展示形状。
举个例子,一个按钮的背景,默认时是一个形状,按下时是一个形状,不可操作时又是另一个形状。有时候,不同状态下改变的不只是背景、图片等,文字颜色也会相应改变。而要处理这些不同状态下展示什么的问题,就要用selector来实现了。
那么,看看都有哪些状态可以设置呢:
android:state_enabled: 设置触摸或点击事件是否可用状态,一般只在false时设置该属性,表示不可用状
android:state_pressed: 设置是否按压状态,一般在true时设置该属性,表示已按压状态,默认为false
android:state_selected: 设置是否选中状态,true表示已选中,false表示未选中
android:state_checked: 设置是否勾选状态,主要用于CheckBox和RadioButton,true表示已被勾选,false表示未被勾选
android:state_checkable: 设置勾选是否可用状态,类似state_enabled,只是state_enabled会影响触摸或点击事件,而state_checkable影响勾选事件
android:state_focused: 设置是否获得焦点状态,true表示获得焦点,默认为false,表示未获得焦点
android:state_window_focused: 设置当前窗口是否获得焦点状态,true表示获得焦点,false表示未获得焦点,例如拉下通知栏或弹出对话框时,当前界面就会失去焦点;另外,ListView的ListItem获得焦点时也会触发true状态,可以理解为当前窗口就是ListItem本身
android:state_activated: 设置是否被激活状态,true表示被激活,false表示未激活,API Level 11及以上才支持,可通过代码调用控件的setActivated(boolean)方法设置是否激活该控件
demo:用于按钮的背景
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_btn_lost_window_focused" android:state_window_focused="false" />
<item android:drawable="@drawable/bg_btn_disable" android:state_enabled="false" />
<item android:drawable="@drawable/bg_btn_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/bg_btn_selected" android:state_selected="true" />
<item android:drawable="@drawable/bg_btn_activated" android:state_activated="true" />
<item android:drawable="@drawable/bg_btn_normal" />
selector>
demo:用于按钮的文本颜色
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/black" android:state_window_focused="false" />
<item android:color="@android:color/background_light" android:state_enabled="false" />
<item android:color="@android:color/holo_blue_light" android:state_pressed="true" />
<item android:color="@android:color/holo_green_dark" android:state_selected="true" />
<item android:color="@android:color/holo_green_light" android:state_activated="true" />
<item android:color="@android:color/white" />
selector>
引用:
注意:
另外,selector标签下有两个比较有用的属性要说一下,添加了下面两个属性之后,则会在状态改变时出现淡入淡出效果,但必须在API Level 11及以上才支持:
最后,关于ListView的ListItem样式,有两种设置方式,一种是在ListView标签里设置android:listSelector属性,另一种是在ListItem的布局layout里设置android:background。但是,这两种设置的结果却有着不同。同时,使用ListView时也有些其他需要注意的地方,总结如下:
第三种是最方便,也是推荐的方式,它会将ListItem根布局下的所有子控件都设置为不能获取焦点。android:descendantFocusability属性的值有三种,其中,ViewGroup是指设置该属性的View,本例中就是ListItem的根布局:
三、layer-list
使用layer-list可以将多个drawable按照顺序层叠在一起显示。
像上图中的Tab,是由一个红色的层加一个白色的层叠在一起显示的结果,阴影的圆角矩形则是由一个灰色的圆角矩形叠加上一个白色的圆角矩形。
demo:Tab背景的代码
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<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" android:drawable="@android:color/white" />
layer-list>
item>
selector>
demo:带阴影的圆角矩形
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<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>
layer-list的item可以通过下面四个属性设置偏移量:
拓展 单边圆角,四边宽度不等
下面共用到3种Drawable
最上方
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#e6e6e6"/>
<corners
android:topLeftRadius="5dp"
android:topRightRadius="5dp"/>
shape>
item>
<item
android:bottom="0.5dp"
android:left="1dp"
android:right="1dp"
android:top="1dp">
<shape>
<solid android:color="#FFFFFF"/>
<corners
android:topLeftRadius="5dp"
android:topRightRadius="5dp"/>
shape>
item>
layer-list>
中间
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#e6e6e6"/>
shape>
item>
<item
android:bottom="0.5dp"
android:left="1dp"
android:right="1dp"
android:top="0.5dp">
<shape>
<solid android:color="#FFFFFF"/>
shape>
item>
layer-list>
最下方
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#e6e6e6"/>
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"/>
shape>
item>
<item
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="0.5dp">
<shape>
<solid android:color="#FFFFFF"/>
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"/>
shape>
item>
layer-list>
style
Android的样式一般定义在res/values/styles.xml文件中,其中有一个根元素
,而具体的每种样式定义则是通过
下的子标签来完成,
通过添加多个
来设置样式不同的属性。
另外,样式是可以继承的,可通过标签的
parent**
属性声明要继承的样式,也可通过点前缀 (.)
继承,点前面为父样式名称,后面为子样式名称。点前缀方式只适用于自定义的样式,若要继承Android内置的样式,则只能通过parent
属性声明。
demo : 继承Widget.Material.Button样式,改变背景和文字颜色
<resources>
<style name="ButtonNormal" parent="@android:style/Widget.Material.Button" >
<item name="android:background">@drawable/bg_btn_selector
- "android:textColor"
>@color/text_btn_selector
style>
resources>
demo: 只想改变文字颜色,但背景想让它透明,这时就可以用点前缀的方式继承以上的样式
<resources>
<style name="ButtonNormal" parent="@android:style/Widget.Material.Button">
<item name="android:background">@drawable/bg_btn_selector
- "android:textColor"
>@color/text_btn_selector
style>
<style name="ButtonNormal.Transparent">
<item name="android:background">@drawable/bg_btn_transparent
- "android:textColor"
>@color/text_btn_selector
style>
resources>
demo : 自定义主题
drawable
图片是最常用的drawable资源,格式包括:png(推荐)、jpg(可接受)、gif(不建议)。用图片资源需要根据不同屏幕密度提供多张不同尺寸的图片,它们的关系如下表:
这里推荐两款切图工具:Cutterman和Cut&Slice me,都是Photoshop下的插件,输出支持android、ios和web三种平台。
另建议尽量减少引入图片,而通过使用shape、layer-list等自己画,易于修改和维护,也减少了安装包大小,适配性也更好。
① bitmap标签
可以通过bitmap标签对图片做一些设置,如平铺、拉伸或保持图片原始大小,也可以指定对齐方式。看看bitmap标签的一些属性吧:
android:src 必填项,指定图片资源,只能是图片,不能是xml定义的drawable资源
android:gravity 设置图片的对齐方式,比如在layer-list中,默认会尽量填满整个视图,导致图片可能会被拉伸,为了避免被拉伸,就可以设置对齐方式,可取值为下面的值,多个取值可以用 |
分隔:
android:antialias 设置是否开启抗锯齿
android:dither 设置是否抖动,图片与屏幕的像素配置不同时会用到,比如图片是ARGB 8888的,而屏幕是RGB565
android:filter 设置是否允许对图片进行滤波,对图片进行收缩或者延展使用滤波可以获得平滑的外观效果
android:tint 给图片着色,比如图片本来是黑色的,着色后可以变成白色
android:tileMode 设置图片平铺的方式,取值为下面四种之一:
android:alpha 设置图片的透明度,取值范围为0.0~1.0之间,0.0为全透明,1.0为全不透明,API Level最低要求是11,即Android 3.0
android:mipMap 设置是否可以使用mipmap,但API Level最低要求是17,即Android 4.2
android:autoMirrored 设置图片是否需要镜像反转,当布局方向是RTL,即从右到左布局时才有用,API Level 19(Android 4.4)才添加的属性
android:tileModeX 和tileMode一样设置图片的平铺方式,只是这个属性只设置水平方向的平铺方式,这是API Level 21(Android 5.0)才添加的属性
android:tileModeY 和tileMode一样设置图片的平铺方式,只是这个属性只设置垂直方向的平铺方式,这是API Level
21(Android 5.0)才添加的属性
android:tintMode 着色模式,也是API Level 21(Android 5.0)才添加的属性
② 点九图片
点九图片文件扩展名为:.9.png,通过点九图片可以做局部拉伸
画点九图一般用Android SDK工具集里的draw9patch工具,只需要在四条边画黑线就可以了,如下图所示:
拉伸区域就是图片会被拉伸的部分,可以为1个点,也可以为一条线,甚至也可以为断开的几个点或几条线,总之,有黑点的地方就会被拉伸,没有黑点的地方就不会被拉伸。而显示内容区域其实就等于默认给使用的控件设置了padding,控件的内容只能显示在内容区域内。
③ inset标签
使用inset标签可以对drawable设置边距,其用法和View的padding类似,只不过padding是设置内容与边界的距离,而inset则可以设置背景drawable与View边界的距离。inset标签的可设置属性如下:
④ level-list标签
当需要在一个View中显示不同图片的时候,比如手机剩余电量不同时显示的图片不同,level-list就可以派上用场了。
level-list可以管理一组drawable,每个drawable设置一组level范围,最终会根据level值选取对应的drawable绘制出来。level-list通过添加item子标签来添加相应的drawable,其下的item只有三个属性:
demo:
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/battery_low"
android:maxLevel="10"
android:minLevel="0" />
<item
android:drawable="@drawable/battery_below_half"
android:maxLevel="50"
android:minLevel="10" />
<item
android:drawable="@drawable/battery_over_half"
android:maxLevel="99"
android:minLevel="50" />
<item
android:drawable="@drawable/battery_full"
android:maxLevel="100"
android:minLevel="100" />
level-list>
那么,当电量剩下XX %时则可以设置level值为10,将会匹配相应的图片:
img.getDrawable().setLevel(XX);
item的匹配规则是从上到下的,当设置的level值与前面的item的level范围匹配,则采用。一般item的添加按maxLevel从小到大排序下来,此时minLevel可以不用指定也能匹配到。如上面代码就可以简化如下:
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/battery_low"
android:maxLevel="10" />
<item
android:drawable="@drawable/battery_below_half"
android:maxLevel="50" />
<item
android:drawable="@drawable/battery_over_half"
android:maxLevel="99" />
<item
android:drawable="@drawable/battery_full"
android:maxLevel="100" />
level-list>
⑤ animation-list标签
通过animation-list可以将一系列drawable构建成帧动画,就是将一个个drawable,一帧一帧的播放。通过添加item子标签设置每一帧使用的drawable资源,以及每一帧持续的时间。示例代码如下:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@drawable/anim1"
android:duration="1000" />
<item
android:drawable="@mipmap/anim2"
android:duration="1000" />
<item
android:drawable="@mipmap/anim3"
android:duration="1000" />
animation-list>
android:oneshot属性设置是否循环播放,设为true时,只播放一轮就结束,设为false时,则会轮询播放。
android:duration属性设置该帧持续的时间,以毫秒数为单位。
animation-list对应的Drawable类为AnimationDrawable,要让动画运行起来,需要主动调用AnimationDrawable的start()方法。另外,如果在Activity的onCreate()方法里直接调用start()方法会没有效果,因为view还没有初始化完成是播放不了动画的。
本文还有很多没有囊括的内容,具体请看转载
转载说明:
转载请注明:转载自Keegan小钢
并标明原文链接:http://keeganlee.me/post/android/20151031