您的位置:首页 > 移动开发 > Android开发

android使用代码生成LayerDrawable的方法和注意事项

2016-03-21 17:46 701 查看
为了有更好的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);

源码为:
/** Specify modifiers to the bounds for the drawable[index].
left += l
top += t;
right -= r;
bottom -= b;
*/
public void setLayerInset(int index, int l, int t, int r, int b) {
ChildDrawable childDrawable = mLayerState.mChildren[index];
childDrawable.mInsetL = l;
childDrawable.mInsetT = t;
childDrawable.mInsetR = r;
childDrawable.mInsetB = b;
}
可以看出setLayerInset()函数的作用就是将某层(层数从0开始计数)相对于上一层进行向里偏移。当然如果传入的数值为负数,就是向外偏移了,不过这时上层就遮挡住下层了,失去了使用layer的意义了。4.padding的作用同样非常重要:(1)当在最上层使用padding时,它指明的是最上层的drawable边缘与内容之间的padding;(2)当在非最上层使用padding时,它指明当前层与上层之间的padding。下面使用java代码生成LayerDrawable。
private void setLayerBg(View view){

int radius0 = 10;
float[] outerR = new float[] { radius0, radius0, radius0, radius0, radius0, radius0, radius0, radius0 };
RoundRectShape roundRectShape0 = new RoundRectShape(outerR, null, null);

int radius1 = 10;
float[] outerR1 = new float[] { radius1, radius1, radius1, radius1, radius1, radius1, radius1, radius1 };
RoundRectShape roundRectShape1 = new RoundRectShape(outerR1, null, null);

ShapeDrawable shapeDrawableBg = new ShapeDrawable();

shapeDrawableBg.setPadding(0, 0, 0, 0);
shapeDrawableBg.setShape(roundRectShape0);

shapeDrawableBg.getPaint().setStyle(Paint.Style.FILL);
shapeDrawableBg.getPaint().setColor(0xffbbbbbb);

ShapeDrawable shapeDrawableFg = new ShapeDrawable();

shapeDrawableFg.setPadding(23, 23, 23, 23);
shapeDrawableFg.setShape(roundRectShape1);

shapeDrawableFg.getPaint().setStyle(Paint.Style.FILL);
shapeDrawableFg.getPaint().setColor(0xffdddddd);

Drawable[] layers = {shapeDrawableBg, shapeDrawableFg};
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerInset(1, 0, 0, 1, 1);

view.setBackgroundDrawable(layerDrawable);

}
注释我就不写了,具体的解释见上面的解析。LayerDrawable和StateListDrawable相结合使用当我们遇到可点击的控件时,需要给此控件自定义几个不同状态的background,比如按下效果、普通状态效果,这时就需要用到StateListDrawable。采用LayerDrawable生成的图片具有的只是静态属性,当将不同状态的LayerDrawable添加到一个StateListDrawable中,这样控件不同状态时均选择是否具有阴影效果。代码如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

text  = (TextView)this.findViewById(R.id.text);
text.setBackgroundDrawable(getStateListDrawable());
text.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "ttt", Toast.LENGTH_SHORT).show();
}
});
}

private Drawable getStateListDrawable(){

StateListDrawable stateListDrawable = new StateListDrawable();

int[] stateHighlighted = new int[]{android.R.attr.state_pressed};
Drawable highlightedDrawable = getLayerDrawable(0xffcccccc);
stateListDrawable.addState(stateHighlighted, highlightedDrawable);

int[] stateNormal = new int[]{};
Drawable normalDrawable = getLayerDrawable(0xffdddddd);
stateListDrawable.addState(stateNormal, normalDrawable);

return stateListDrawable;
}

private Drawable getLayerDrawable(int foregroundColor){

int radius0 = 10;
float[] outerR = new float[] { radius0, radius0, radius0, radius0, radius0, radius0, radius0, radius0 };
RoundRectShape roundRectShape0 = new RoundRectShape(outerR, null, null);

int radius1 = 10;
float[] outerR1 = new float[] { radius1, radius1, radius1, radius1, radius1, radius1, radius1, radius1 };
RoundRectShape roundRectShape1 = new RoundRectShape(outerR1, null, null);

ShapeDrawable shapeDrawableBg = new ShapeDrawable();
shapeDrawableBg.setPadding(0, 0, 0, 0);
shapeDrawableBg.setShape(roundRectShape0);
shapeDrawableBg.getPaint().setStyle(Paint.Style.FILL);
shapeDrawableBg.getPaint().setColor(0xffbbbbbb);

ShapeDrawable shapeDrawableFg = new ShapeDrawable();
shapeDrawableFg.setPadding(23, 23, 23, 23);
shapeDrawableFg.setShape(roundRectShape1);
shapeDrawableFg.getPaint().setStyle(Paint.Style.FILL);
shapeDrawableFg.getPaint().setColor(foregroundColor);

Drawable[] layers = {shapeDrawableBg, shapeDrawableFg};
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerInset(1, 0, 0, 1, 1);

return layerDrawable;
}
需要注意的是:当给View、TextView、ImageView、ViewGroup等类型的默认没有按下事件的控件添加StateListDrawable时,控件需要设置上click事件,否则按下效果不起作用备注:这里只是通过两幅颜色单一的drawable错位简单的生成“阴影效果”,后续可以通过shader等效果,生成逐渐淡出的“阴影”效果。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: