为了有更好的UI体验,一般我们会把button、textview等控件的背景设置上阴影。传统的做法是美工提供一张具有阴影效果的nine patch图,然后将其在xml文件中添加到background属性。这种做法没有问题,不过缺乏灵活性。

图1.使用代码生成的具有“阴影”效果的控件

在android中,每一种在xml文件中定义的图片,均可以使用java代码生成,其中LayerDrawable对应的xml文件的根元素为<layer-list>。

首先我介绍一下使用xml文件生成“阴影”背景效果图片:

<?xml version= "1.0" encoding ="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" ><item ><shape android:shape="rectangle" ><solid android:color="#ffbbbbbb" /><corners android:radius="2dp" /></shape></item ><itemandroid:bottom="1px"android:right="1px" ><shape android:shape="rectangle" ><solid android:color="#ffdddddd" /><corners android:radius="2dp" /><paddingandroid:bottom="10dp"android:left="10dp"android:right="10dp"android:top="10dp" /></shape></item ></layer-list>

解析:

1.shape元素生成ShapeDrawable对象,不过需要注意的是,xml中虽然指明生成"rectangle"类型的对象,但如果想要在java中生成的rectangle具有圆角,那么java中对应的shape应该是RoundRectShape。2.solid元素指明背景颜色,且paint的style为fill。3.第二个元素android:bottom等代表的是LayerDrawable中第二个drawable相对于第一个drawable的inset,对应的java代码为:layerDrawable.setLayerInset(1, 0, 0, 1, 1);
源码为:
 1 /** Specify modifiers to the bounds for the drawable[index].
 2         left += l
 3         top += t;
 4         right -= r;
 5         bottom -= b;
 6     */
 7     public void setLayerInset(int index, int l, int t, int r, int b) {
 8         ChildDrawable childDrawable = mLayerState.mChildren[index];
 9         childDrawable.mInsetL = l;
10         childDrawable.mInsetT = t;
11         childDrawable.mInsetR = r;
12         childDrawable.mInsetB = b;
13     }

可以看出setLayerInset()函数的作用就是将某层(层数从0开始计数)相对于上一层进行向里偏移。当然如果传入的数值为负数,就是向外偏移了,不过这时上层就遮挡住下层了,失去了使用layer的意义了。

4.padding的作用同样非常重要:

(1)当在最上层使用padding时,它指明的是最上层的drawable边缘与内容之间的padding;

(2)当在非最上层使用padding时,它指明当前层与上层之间的padding。

下面使用java代码生成LayerDrawable。

 1 private void setLayerBg(View view){
 2
 3         int radius0 = 10;
 4         float[] outerR = new float[] { radius0, radius0, radius0, radius0, radius0, radius0, radius0, radius0 };
 5         RoundRectShape roundRectShape0 = new RoundRectShape(outerR, null, null);
 6
 7         int radius1 = 10;
 8         float[] outerR1 = new float[] { radius1, radius1, radius1, radius1, radius1, radius1, radius1, radius1 };
 9         RoundRectShape roundRectShape1 = new RoundRectShape(outerR1, null, null);
10
11         ShapeDrawable shapeDrawableBg = new ShapeDrawable();
12
13         shapeDrawableBg.setPadding(0, 0, 0, 0);
14         shapeDrawableBg.setShape(roundRectShape0);
15
16         shapeDrawableBg.getPaint().setStyle(Paint.Style.FILL);
17         shapeDrawableBg.getPaint().setColor(0xffbbbbbb);
18
19
20         ShapeDrawable shapeDrawableFg = new ShapeDrawable();
21
22         shapeDrawableFg.setPadding(23, 23, 23, 23);
23         shapeDrawableFg.setShape(roundRectShape1);
24
25         shapeDrawableFg.getPaint().setStyle(Paint.Style.FILL);
26         shapeDrawableFg.getPaint().setColor(0xffdddddd);
27
28         Drawable[] layers = {shapeDrawableBg, shapeDrawableFg};
29         LayerDrawable layerDrawable = new LayerDrawable(layers);
30         layerDrawable.setLayerInset(1, 0, 0, 1, 1);
31
32         view.setBackgroundDrawable(layerDrawable);
33
34     }

注释我就不写了,具体的解释见上面的解析。

LayerDrawable和StateListDrawable相结合使用

当我们遇到可点击的控件时,需要给此控件自定义几个不同状态的background,比如按下效果、普通状态效果,这时就需要用到StateListDrawable。

采用LayerDrawable生成的图片具有的只是静态属性,当将不同状态的LayerDrawable添加到一个StateListDrawable中,这样控件不同状态时均选择是否具有阴影效果。

代码如下:

 1 @Override
 2     protected void onCreate(Bundle savedInstanceState) {
 3         super.onCreate(savedInstanceState);
 4         setContentView(R.layout.activity_main);
 5
 6         text  = (TextView)this.findViewById(R.id.text);
 7         text.setBackgroundDrawable(getStateListDrawable());
 8         text.setOnClickListener(new View.OnClickListener() {
 9
10             @Override
11             public void onClick(View v) {
12                 Toast.makeText(getApplicationContext(), "ttt", Toast.LENGTH_SHORT).show();
13             }
14         });
15    }
16
17     private Drawable getStateListDrawable(){
18
19         StateListDrawable stateListDrawable = new StateListDrawable();
20
21         int[] stateHighlighted = new int[]{android.R.attr.state_pressed};
22         Drawable highlightedDrawable = getLayerDrawable(0xffcccccc);
23         stateListDrawable.addState(stateHighlighted, highlightedDrawable);
24
25         int[] stateNormal = new int[]{};
26         Drawable normalDrawable = getLayerDrawable(0xffdddddd);
27         stateListDrawable.addState(stateNormal, normalDrawable);
28
29         return stateListDrawable;
30     }
31
32     private Drawable getLayerDrawable(int foregroundColor){
33
34         int radius0 = 10;
35         float[] outerR = new float[] { radius0, radius0, radius0, radius0, radius0, radius0, radius0, radius0 };
36         RoundRectShape roundRectShape0 = new RoundRectShape(outerR, null, null);
37
38         int radius1 = 10;
39         float[] outerR1 = new float[] { radius1, radius1, radius1, radius1, radius1, radius1, radius1, radius1 };
40         RoundRectShape roundRectShape1 = new RoundRectShape(outerR1, null, null);
41
42         ShapeDrawable shapeDrawableBg = new ShapeDrawable();
43         shapeDrawableBg.setPadding(0, 0, 0, 0);
44         shapeDrawableBg.setShape(roundRectShape0);
45         shapeDrawableBg.getPaint().setStyle(Paint.Style.FILL);
46         shapeDrawableBg.getPaint().setColor(0xffbbbbbb);
47
48         ShapeDrawable shapeDrawableFg = new ShapeDrawable();
49         shapeDrawableFg.setPadding(23, 23, 23, 23);
50         shapeDrawableFg.setShape(roundRectShape1);
51         shapeDrawableFg.getPaint().setStyle(Paint.Style.FILL);
52         shapeDrawableFg.getPaint().setColor(foregroundColor);
53
54         Drawable[] layers = {shapeDrawableBg, shapeDrawableFg};
55         LayerDrawable layerDrawable = new LayerDrawable(layers);
56         layerDrawable.setLayerInset(1, 0, 0, 1, 1);
57
58         return layerDrawable;
59     }

需要注意的是:当给View、TextView、ImageView、ViewGroup等类型的默认没有按下事件的控件添加StateListDrawable时,控件需要设置上click事件,否则按下效果不起作用

备注:

这里只是通过两幅颜色单一的drawable错位简单的生成“阴影效果”,后续可以通过shader等效果,生成逐渐淡出的“阴影”效果。

使用xml定义layer-list的示例:

使用layer-list定义的xml作为button的背景。其中:

Button1:
1.底部drawable没有设置padding
2.顶部drawable没有设置padding
3.顶部drawable设置inset为5px

        android:left="5px"android:top="5px"android:bottom="5px"android:right="5px"

button1背景的完整xml:

<?xml version= "1.0" encoding ="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" ><item ><shape android:shape="rectangle" ><solid android:color="#ff00ff00" /><corners android:radius="3dp" /></shape></item ><itemandroid:left="5px"android:top="5px"android:bottom="5px"android:right="5px" ><shape android:shape="rectangle" ><solid android:color="#ffff0000" /><corners android:radius="3dp" /></shape></item ></layer-list>    

Button2:
1.底部drawable没有设置padding
2.顶部drawable设置inset均为5px

        android:left="5px"android:top="5px"android:bottom="5px"android:right="5px"

3.顶部drawable设置padding均为50dp

     <paddingandroid:bottom="50dp"android:left="50dp"android:right="50dp"android:top="50dp" />

button2背景的完整xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" ><!-- Z-Order 底部drawable --><item ><shape android:shape="rectangle" ><solid android:color="#ff00ff00" /><corners android:radius="3dp" /></shape></item ><!-- 顶部drawable --><itemandroid:left="5px"android:top="5px"android:bottom="5px"android:right="5px" ><shape android:shape="rectangle" ><solid android:color="#ffff0000" /><corners android:radius="3dp" /><paddingandroid:bottom="50dp"android:left="50dp"android:right="50dp"android:top="50dp" /></shape></item ></layer-list>

Button3:
1.底部drawable设置padding均为20dp
2.顶部drawable没有设置inset
3.顶部drawable设置padding均为50dp

    <paddingandroid:bottom="50dp"android:left="50dp"android:right="50dp"android:top="50dp" />

button3背景的完整xml:

<?xml version= "1.0" encoding ="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" ><item><shape android:shape="rectangle" ><solid android:color="#ff00ff00" /><corners android:radius="3dp" /><paddingandroid:bottom="20dp"android:left="20dp"android:right="20dp"android:top="20dp" /></shape></item><item><shape android:shape="rectangle" ><solid android:color="#ffff0000" /><corners android:radius="3dp" /><paddingandroid:bottom="50dp"android:left="50dp"android:right="50dp"android:top="50dp" /></shape></item></layer-list>    


转载于:https://www.cnblogs.com/carbs/p/5302908.html

[原创]android使用代码生成LayerDrawable的方法和注意事项相关推荐

  1. Android中实现震动的方法

    https://blog.csdn.net/bruceyangjie/article/details/53283899 Android中实现震动的方法 版权声明:本文为博主原创文章,未经博主允许不得转 ...

  2. [原创]Android Monkey测试工具使用介绍

    [原创]Android Monkey测试工具使用介绍 1 Android Monkey介绍 Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件 ...

  3. android 安全 权限,[原创]Android 中的那些权限

    [原创]Android 中的那些权限 2013-5-9 20:04 4610 [原创]Android 中的那些权限 2013-5-9 20:04 4610 1.        随着智能手机的普及,越来 ...

  4. android盒子开发招聘,[原创]Android沙盒开发之系统libc库定制修改

    [原创]Android沙盒开发之系统libc库定制修改 2013-7-29 22:29 11525 [原创]Android沙盒开发之系统libc库定制修改 2013-7-29 22:29 11525 ...

  5. unity3d android包太大了,unity/unity3d编译成android apk包瘦身方法

     unity/unity3d编译成android apk包瘦身方法 本文系原创,请转发的朋友带上我的链接. 相信用unity开发的同学都会遇到类似的经历:明明资源图片不大,但是发现打包后apk文件 ...

  6. Xposed: 勾住(Hook) Android应用程序对象的方法,实现AOP

    Xposed Xposed能够勾住(Hook) Android应用程序对象的方法,实现AOP,一个简单的例子: public class WebViewHook implements IXposedH ...

  7. [原创]Android Monkey 在线日志分析工具开发

    [原创]Android Monkey 在线日志分析工具开发 在移动App测试过程中,Monkey测试是我们发现潜在问题的一种非常有效手段,但是Android原生的Monkey有其天然的不足,数据不能有 ...

  8. MyEclipse 10 中安装Android ADT 22插件的方法

    MyEclipse 10 中安装Android ADT 22插件的方法 下载ADT包:http://dl.google.com/android/ADT-22.0.0.zip 将ADT-22.0.0.z ...

  9. android 按钮放中间,Android实现button居中的方法

    本文实例讲述了Android实现button居中的方法.分享给大家供大家参考.具体如下: 通过在main.xml 或者其他xml 布局文件中布局Button的时候,选择Android:gravity= ...

最新文章

  1. Java重写父类使用@Override时出现The method destroy() of type xxx must override a superclass method的问题解决...
  2. 清华大学 唐杰 计算机学院 怎么样,我国首位原创虚拟学生,后期希望“她”能够像人一样进行创新...
  3. android手机短信拦截器,垃圾短信退订套路深 手机上装拦截软件是可行方法
  4. java collections读书笔记(4) stack
  5. Struts2.3,s:iterator,c:forEach遍历map中的list集合
  6. 五、Spring中的@Import注解
  7. bzoj2462 [BeiJing2011]矩阵模板 hash
  8. 嘿嘿,俺做长辈了!!!
  9. nginx限制请求之一:(ngx_http_limit_conn_module)模块
  10. 【蓝桥杯历年题】2020蓝桥杯A组省赛第二场(10.17)【含蓝桥杯官网提交地址】
  11. Canon iC MF8350Cdn打印机驱动安装,解决内存不能为written问题
  12. python切片原理_彻底理解Python list切片原理
  13. java求面积_Java计算几何图形的面积
  14. R语言学习笔记(四)--数据结构
  15. 破解word只读文档 word文档保护后的破解办法
  16. 火到服务器瘫痪了,这款小游戏太火爆了,合成大西瓜
  17. word如何取消封面或者目录下方的页码,页码从正文开始
  18. gpt2_gpt 3,一开始是单词2 2
  19. 【5G RLC】AM模式的数据传输详解
  20. 《iOS Drawing Practical UIKit Solutions》读书笔记(四) —— 遮罩,模糊和动画

热门文章

  1. 设计模式_1_工厂模式与抽象工厂
  2. Vue3 高级语法(一)—— h函数、jsx
  3. LeetCode 361. 轰炸敌人(前缀和DP)
  4. LeetCode 158. 用 Read4 读取 N 个字符 II
  5. LeetCode 1381. 设计一个支持增量操作的栈(deque/数组)
  6. POJ 1276 ATM凑钱(动态规划)(未解答)
  7. 数据结构--链表--单链表中环的检测,环的入口,环的长度的计算
  8. spring手动回滚事务_Spring总结---gt;03
  9. 文献阅读:知识图谱数据管理研究综述
  10. sklearn分类器性能评估