【转】Android使用XML Shape绘制带阴影效果的圆形按钮
众所周知,在Android开发里,为了优化在各种分辨率设备上的显示效果,同一份图片素材往往要提供mdpi、hdpi、xhdpi三种(以前还有ldpi),
尤其是按钮类的素材,考虑到normal、pressed、focused更是需要至少3×3=9张图片。NinePatch技术虽然可以解决一部分尺寸灵活性的问题,
但大部分修改和适配还是要再次制作一批图片的。
根据交互设计的需要,可以考虑用Drawable的XML绘制按钮,好处有:
* 矢量绘制,易于缩放;
* 字节数更少(一般而言);
* 基于XML文本,属性值易于调整;
* Drawable组件间可嵌套,可重用;
* XML与项目其他源代码在一起,便于版本控制。
当然也有缺点:
* 没有可视化的编辑器,编辑不够直观;
* 受限于基本的图形和填充方式;
* 美工人员很难上手。
以本站开发的习作《泡面管家》(参见这里)为例。
下图是泡面管家的计时器,中间的圆形(包含镂空阴影效果)默认是表示计时器状态的icon,在计时器运行期间会变换为停止计时的按钮:

这里icon的背景是用Drawable XML绘制的。在Android中,Drawable XML并不支持阴影,参考了网上诸多例子,一般都是以额外绘制的渐变或者边框来实现阴影。
这里是用叠加shape的方式来绘制的。

上图中绿色方框中的标识的色块,从外到内可以划分成几个部分:
* Outer circle
* Inner shadow of outer circle
* Gap
* Outer shadow of center circle
* Center circle
使用<layer-list/>,从最底层开始,画对应最外部分的、最大的圆形,然后逐层的、边扩大padding边叠加圆形,圆形的填充颜色要对应到相应的色块。
res/drawable/timer_center_bg.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- outer circle -->
<item>
<shape android:shape="oval" >
<solid android:color="#FFACB8C3" />
</shape>
</item> <!-- inner shadow of outer circle -->
<item
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp">
<shape android:shape="oval">
<solid android:color="#FFbdcad6" />
</shape>
</item>
<item
android:bottom="3dp"
android:left="3dp"
android:right="3dp"
android:top="3dp">
<shape android:shape="oval">
<solid android:color="#FFc3cfd9" />
</shape>
</item>
<item
android:bottom="4dp"
android:left="4dp"
android:right="4dp"
android:top="4dp">
<shape android:shape="oval">
<solid android:color="#FFcbd6df" />
</shape>
</item>
<item
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp">
<shape android:shape="oval">
<solid android:color="#FFd4dee5" />
</shape>
</item> <!-- gap -->
<item
android:bottom="6dp"
android:left="6dp"
android:right="6dp"
android:top="6dp">
<shape android:shape="oval" >
<solid android:color="#FFdae2e8" />
</shape>
</item> <!-- outer shadow of center circle -->
<item
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp">
<shape android:shape="oval">
<solid android:color="#FFced5dc" />
</shape>
</item>
<item
android:bottom="12dp"
android:left="12dp"
android:right="12dp"
android:top="12dp">
<shape android:shape="oval">
<solid android:color="#FFbcc4c9" />
</shape>
</item>
<item
android:bottom="13dp"
android:left="13dp"
android:right="13dp"
android:top="13dp">
<shape android:shape="oval">
<solid android:color="#FFb4bbc0" />
</shape>
</item>
<item
android:bottom="14dp"
android:left="14dp"
android:right="14dp"
android:top="14dp">
<shape android:shape="oval">
<solid android:color="#FFacb3b8" />
</shape>
</item> <!-- center circle -->
<item
android:bottom="15dp"
android:left="15dp"
android:right="15dp"
android:top="15dp">
<shape android:shape="oval">
<stroke android:width="1dp" android:color="#FFFCFCFC"/>
<gradient
android:angle="270"
android:endColor="#FFCFD7DD"
android:startColor="#FFF0F5F9" />
</shape>
</item> </layer-list>
从以上代码中可以看出,只是简单的圆形的叠加,就可以绘制出具有立体感的按钮。要注意上边只是按钮的背景。文章开头也讲过,Drawable XML的特征之一就是可复用。
继续看res/drawable/stop_timer_btn.xml的代码:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- normal -->
<item android:state_enabled="true" android:state_focused="false" android:state_pressed="false">
<layer-list>
<item android:drawable="@drawable/timer_center_bg" />
<item android:bottom="15dp" android:left="15dp" android:right="15dp" android:top="15dp">
<shape android:shape="oval">
<stroke android:width="1dp" android:color="#FFFCFCFC" />
<gradient android:angle="270" android:endColor="#FF91c0e8" android:startColor="#FFa7d3fa" />
</shape>
</item>
</layer-list>
</item> <!-- pressed -->
<item android:state_enabled="true" android:state_pressed="true">
<layer-list>
<item android:drawable="@drawable/timer_center_bg" />
<item android:bottom="15dp" android:left="15dp" android:right="15dp" android:top="15dp">
<shape android:shape="oval">
<stroke android:width="2dp" android:color="#FFf8f640" />
<gradient android:angle="270" android:endColor="#FF91c0e8" android:startColor="#FFa7d3fa" />
</shape>
</item>
</layer-list>
</item> <!-- selected -->
<item android:state_enabled="true" android:state_focused="true" android:state_pressed="false">
<layer-list>
<item android:drawable="@drawable/timer_center_bg" />
<item android:bottom="15dp" android:left="15dp" android:right="15dp" android:top="15dp">
<shape android:shape="oval">
<stroke android:width="2dp" android:color="#FFf8f640" />
<gradient android:angle="270" android:endColor="#FF91c0e8" android:startColor="#FFa7d3fa" />
</shape>
</item>
</layer-list>
</item> <!-- ...... -->
</selector>
上述代码以看出,<selector/>中每个<item/>都是一个<layer-list/>,将@drawable/timer_center_bg作为背景在前景叠加圆形以区分不同状态。
最后要说明的是,决定一个按钮应该是否用Drawable XML渲染,应考虑以下几个因素:
* App是否要支持多分辨率;
* App是否有瘦身的需要;
* 图案是否足够简单;
* 图案需要自由缩放;
* 设计开发工作流程是否容许开发人员跨界;
* 开发人力相对于设计人力更充足。
否则,应该考虑以图片方式渲染。
【转】Android使用XML Shape绘制带阴影效果的圆形按钮的更多相关文章
- android 开发 xml绘制shape与Selector与layer-list 一 基础篇
首先我们先来了解状态效果 android:state_pressed=["true" | "false"] 按下状态 android:state_focuse ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- 【Android使用Shape绘制虚线,在4.0以上的手机显示实线】解决方式
问题描写叙述: 用下面代码绘制虚线: <span style="font-family:Comic Sans MS;font-size:18px;"><? xml ...
- Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android开发——xml知识之xml可绘制对象简介
引言:摘录Android用户界面设计 Android支持各类xml可绘制对象,其中一些可绘制对象可用于实现让一个资源使用多个图片文件,另外一些则允许你在xml中真正地指定颜色,还有一些你从来都不会用到 ...
- 【转】Android Shape绘制虚线在手机端查看是实线的问题
Android share绘制虚线在手机上显示实线问题 给控件添加Drawableleft等图片后,单独给图片设置动画效果,参考文章: http://blog.csdn.net/langzxz/art ...
- 030 Android 第三方开源下拉框:NiceSpinner的使用+自定义Button样式+shape绘制控件背景图+图片选择器(selector)
1.NiceSpinner下拉框控件介绍 Android原生的下拉框Spinner基本上可以满足Android开发对于下拉选项的设计需求,但现在越来越流行的下拉框不满足于Android原生提供的下拉框 ...
- [UI]实用案例--Shape绘制实用圆圈
Android允许通过xml定义资源,常见的事string,id,integer,dimen等,也可以定义一些图片资源,比如用来做几何的矢量图就非常好用,其中有许多的细节问题,具体需求可以再结合goo ...
- Android中的shape
在Android程序开发中,我们经常会去用到Shape这个东西去定义各种各样的形状,shape可以绘制矩形环形以及椭圆,所以只需要用椭圆即可,在使用的时候将控件比如imageview或textview ...
随机推荐
- Java Servlet DAO实践(二)
Java Servlet DAO实践(二) DAO连接类 package com.seller.servlets.dao; import java.sql.*; public class DataBa ...
- (转)WKT转换工具terraformers
http://blog.csdn.net/gisshixisheng/article/details/53150111 概述: 前面的文章中,提到了Arcgis中实现wkt转换为geometry,但是 ...
- xmpp使用经验
IM 标准协议有XMPP\IMPP\PRIM\SIP(SIMPLE)等,其中XMPP基于XML的协议,具备了很好的扩展性(依靠XML的域名空间)并且可以建立在TLS上使用SASL认证. 1.文件比如图 ...
- 第一章 Linux命令行简介
1 Linux系统命令操作语法的格式 命令_[参数选项]_[文件或路径] 其中 _ 至少一个空格 如:rm -f /etc/hosts 其中/etc/hosts完整路径不带空格 ...
- 网络基础——UDP
UDP 1.UDP首部格式 源端口号(16) 目标端口号(16) UDP长度(16) UDP校验和(16) UDP长度:用来指出UDP的总长度 校验和:用来完成对UDP数据的差错检验,它是UDP协议提 ...
- Flask蓝图基本使用
Flask蓝图基本使用 Flask通过使用蓝图将视图函数模块化,使应用显得更加规整 比如我们的应用的视图函数包括用户相关和文章相关,那么我们可以通过建立两个py文件分别存储两类视图函数 user.py ...
- Codeforces 989C - A Mist of Florescence
传送门:http://codeforces.com/contest/989/problem/C 这是一个构造问题. 构造一张网格,网格中的字符为’A’.’B’.’C’.’D’,并且其连通块的个数分别为 ...
- 九度oj 题目1078:二叉树遍历
题目1078:二叉树遍历 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5326 解决:3174 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历 ...
- 撸呀撸的左手(KMP+DP)
题目描述 撸呀撸很迷茫,因为他的左手总是不受控制,做一些不雅的事情.于是撸呀撸一狠心,决定戒撸.没想到,他的左手受不了寂寞,一闲下来就在键盘上各种乱敲. 唔,神奇的左手表示,safasfasaafaf ...
- spring-boot | 整合通用Mabatis 分页插件PageHelper
Mybatis通用Mapper介绍 Mybatis 通用 Mapper 极其方便的使用 Mybatis 单表的增删改查,支持单表操作,不支持通用的多表联合查询 优点: 通用 Mapper 可以极大的方 ...