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等效果,生成逐渐淡出的“阴影”效果。
相关文章推荐
- 在元心操作系统实现对Android Camera HAL3.2的支持
- Android中的双向链表
- Android Studio 默认debug证书位置在哪里(Mac os)
- android原生控制web返回上一页--笔记
- Android:AsyncTaskUtil 异步简化操作工具类
- Android-图片的上传及加载
- android自己获取并保存错误日志(可以通过邮件发送到自己邮箱)
- android camera HAL v3.0概述
- Android NDK带来什么
- android中的回调-接口回调
- 使用native程序来守护android进程
- Android开发学习笔记:Intent的简介以及属性的详解
- Android 实现手势滑动界面(ViewPager)
- SuperNotCalledException
- Android Native开发显示HTML内容
- Android中循环的几种方式
- Android ListView 点击选中效果
- 安卓入门学习(一)从布局XML到视图对象
- Android中error inflating class fragment问题
- Android App中DrawerLayout抽屉效果的菜单编写实例