为了有更好的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 > <item android:bottom="1px" android:right="1px" > <shape android:shape="rectangle" > <solid android:color="#ffdddddd" /> <corners android:radius="2dp" /> <padding android: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 }
注释我就不写了,具体的解释见上面的解析。
备注:
这里只是通过两幅颜色单一的drawable错位简单的生成“阴影效果”,后续可以通过shader等效果,生成逐渐淡出的“阴影”效果。
时间: 2024-11-03 21:25:16