赞
踩
drawable是一种可以在Canvas上进行绘制的抽象的概念,颜色图片都可以是一个drawable,Drawable可以通过XML定义,或者通过代码创建,Android中的drawable是一个抽象类,每个具体的Drawable都是其子类
优点:使用简单,比自定义view成本低,占用空间小,可以减少apk大小
表示一张图片,可以直接引用原始图片或者通过XML进行描述
属性 | 作用 | 备注 |
---|---|---|
android:src | 图片资源ID | |
android:antialias | 图片抗锯齿-图片平滑,清晰度降低 | |
android:dither | 开启抖动效果-用于高质量图片在低质量屏幕上保存较好的显示效果(不会失真) | 应该开启 |
android:filter | 开启过滤-在图片尺寸拉伸和压缩时保持较好的显示效果 | 应该开启 |
android:gravity | 图片小于容器尺寸时,对图片进行定位-选项之间用‘ | ’来组合使用 |
android:mipMap | 纹理映射-图像处理技术 | 默认false |
android:tileMode | 平铺模式-repeat单纯重复、mirror镜面反射、clamp图片四周像素扩散 | 默认disable关闭 |
自动根据宽高进行缩放不会失真
实际使用,可以直接引用图片或者通过XML描述
通过颜色来构造的图形,可以是纯色的图形,也可以是有渐变效果的图形,shape
标签创建的Drawable实体是GradientDrawable
使用:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp"/> <gradient android:angle="45" android:centerX="30" android:centerY="30" android:centerColor="@color/colorAccent" android:endColor="@color/colorPrimary" android:startColor="@color/colorPrimaryDark" android:gradientRadius="20" android:type="linear" android:useLevel="true" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> <size android:width="200dp" android:height="200dp" /> <solid android:color="@color/colorPrimary"/> <stroke android:width="10dp" android:color="@color/colorAccent" android:dashWidth="5dp" android:dashGap="3dp"/> </shape>
属性/标签 | 作用 | 备注 |
---|---|---|
android:shape | 图形的形状:rectangle矩形、oval椭圆、line横线、ring圆环 | corners 标签对应于矩形;line和ring通过stroke 指定线的宽度和颜色; ring圆环有五个特殊的shape属性 |
corners 标签 | 四个角的角度 | |
gradient 标签 | 渐变效果-android:angle表示渐变角度,必须为45的倍数 | android:type指明渐变类型:linear线性,radial径向、sweep扫描 |
solid 标签 | 纯色填充 | 与gradient标签排斥 |
stroke 标签 | 描边 | 有描边线和虚线 |
size 标签 | 表示shape的固有大小,并非最终显示的大小 | 没有时getIntrinsicWidth返回-1;能指明Drawable的固有宽高,但如果作为View背景还是会被拉伸 |
XMl标签为layer-list,层次化的Drawable合集,可以包含多个item,每个item表示一个Drawable item中可以通过android:drawable
直接引用资源,android:top
等表示Drawable相当于View上下左右的偏移量
使用:
<?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="#0ac39e"/> </shape> </item> <item android:bottom="6dp"> <shape android:shape="rectangle"> <solid android:color="#FFFFFF"/> </shape> </item> <item android:bottom="1dp" android:left="1dp" android:right="1dp"> <shape android:shape="rectangle"> <solid android:color="#FFFFFF"/> </shape> </item> </layer-list>
对应于selector
标签,用于View根据状态选择不同的Drawable
使用:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="false" //StateListDrawable的固有大小是否根据状态而改变,默认false=根据状态而改变 android:dither="true" //是否开启抖动-让高质量图片在低质量屏幕上依旧效果好,默认true开启 android:variablePadding="false" //padding是否根据状态的改变而改变,不建议开启(false) > <item android:state_pressed="true" //Button被按下后却没有松开的状态 android:drawable="@color/colorAccent"/> <item android:state_focused="true" //View获取了焦点 android:drawable="@color/colorPrimary"/> <item android:state_selected="true" //用户选择了View android:drawable="@color/colorPrimary"/> <item android:state_checked="true" //用户选中了View,一般用于CheckBox这类在选中和没有选中状态之间切换的View android:drawable="@drawable/ic_launcher_background"/> <item android:state_enabled="true" //View处于可用状态 android:drawable="@drawable/ic_launcher_foreground"/> <item android:drawable="#FFFFFF"/> //默认Drawable: 按顺序向下匹配,需要放在最下方,因为可以匹配任何状态 </selector>
对应于level-list
标签,拥有多个item,每个item都有maxLevel
和minLevel
,Level
的范围为0~10000
,给定level后,会按从上至下
的顺序匹配,直到找到范围合适的Drawable,并返回,item的level一定要降序或者升序,调用View的getBackground
获得Drawable对象,并调用setLevel
设置等级level
,ImageView的setImageLevel()
能快速指定src
引用的Drawable的Level
,LevelListDrawable是根据level
改变,选择不同的Drawable,能用于实现进度条、音量调节等等
使用:
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:minLevel="0" android:maxLevel="10" android:drawable="@drawable/d1" />
<item android:minLevel="11" android:maxLevel="20" android:drawable="@drawable/d2" />
<item android:minLevel="21" android:maxLevel="30" android:drawable="@drawable/d3" />
<item android:minLevel="31" android:maxLevel="40" android:drawable="@drawable/d4" />
</level-list>
对应于transition
标签,实现两个Drawable之前的淡入淡出效果,获得背景的TransitionDrawable
后,通过startTransition
和reverseTransition
方法实现效果和逆过程
使用:
Glide.with(this) .load(prcUrl) .format(DecodeFormat.PREFER_ARGB_8888) .into(object : CustomTarget<Drawable>() { override fun onResourceReady( resource: Drawable, transition: Transition<in Drawable>? ) { val mPrePosterDrawable = mResultPosterDrawable if(resource is BitmapDrawable){ val bitmap = resource.bitmap if(bitmap != null) { val tempBitmap = Bitmap.createBitmap(bitmap) mResultPosterDrawable = BitmapDrawable(resources, tempBitmap) VodLogUtils.d(TAG, "mResultPosterDrawable=$mResultPosterDrawable" ) } } if(mResultPosterDrawable == null) { VodLogUtils.d(TAG, "mResultPosterDrawable is null" ) return } try { val transitionDrawable = if(mPrePosterDrawable == null || (mPrePosterDrawable is BitmapDrawable && mPrePosterDrawable.bitmap == null) || (mPrePosterDrawable is BitmapDrawable && mPrePosterDrawable.bitmap.isRecycled)){ VodLogUtils.d(TAG, "mPrePosterDrawable is null" ) TransitionDrawable(arrayOf(ResourcesCompat.getDrawable(resources,R.drawable.vod_common_dialog_player_mask, null), mResultPosterDrawable)) } else { TransitionDrawable(arrayOf(mPrePosterDrawable, mResultPosterDrawable)) } transitionDrawable.isCrossFadeEnabled = false transitionDrawable.startTransition(500) mMaskView.background = transitionDrawable } catch (e: Exception) { e.printStackTrace() } } override fun onLoadCleared(placeholder: Drawable?) {} })
实现两张图片渐隐渐显
对应inset
标签,将其他Drawable内嵌到自身,并在四周留出间距,View需要背景比自己实际区域要小的时候,可以使用inset
,layer-list
也可以实现该需求
使用:
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_launcher"
android:insetTop="10dp"
android:insetBottom="10dp"
android:insetLeft="10dp"
android:insetRight="10dp">
</inset>
对应于scale标签
根据自己的等级level(0~10000)将指定的Drawable缩放到一定比例
android:scaleHeight="70%"用于指定宽高的缩放比例=为原来的30%
ScaleDrawable的level为0,不可见。为10000时,不缩放。
一般将level设置为1,就会按照属性指定的比例缩放。其他值也会改变缩放效果。
android:scaleGravity属性和gravity属性完全一致
使用:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_launcher"
android:scaleGravity="center"
android:scaleHeight="70%"
android:scaleWidth="70%">
</scale>
对应于clip
标签
根据自己当前的等级level
(0~10000)来裁剪另一个Drawable
裁剪方向由clipOrientation
和gravity
属性共同控制
level
为0,Drawable不可见;10000表示不裁剪;为8000,表示裁减了2000;为1,表示裁剪了9999
对应于animation-list标签
用于实现逐帧动画效果
android:oneShot决定是循环播放还是播放一次,false:循环播放
item中设置一帧一帧的Drawable以及持续时间
AnimationDrawable的setOneShot(boolean flag) 和android:oneShot配置一样
addFrame (Drawable frame, int duration) 动态的添加一个图片进入该动画中
stop()和start()用于停止和开始/继续播放,停止时会停留在当前一帧上
使用:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/shake_anim_01" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_02" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_03" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_04" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_05" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_06" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_07" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_08" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_09" android:duration="100"/>
<item android:drawable="@drawable/shake_anim_10" android:duration="100"/>
</animation-list>
val imageview = findViewById<ImageView>(R.id.imaview)
(imageview.drawable as AnimationDrawable).start() //开始播放
用于获得有shape形状
的drawable
(椭圆、长方形、扇形以及更为通用PaintDrawable-具有圆角和边界)
/**=================================================== * 一个继承自ShapeDrawable更为通用的Drawable:具有圆角 *====================================================*/ PaintDrawable drawable3 = new PaintDrawable(Color.GREEN); drawable3.setCornerRadius(30); findViewById(R.id.textView3).setBackgroundDrawable(drawable3); /**============================================ * 通过Shape构造出相应的ShapeDrawable *=============================================*/ //椭圆形形状 : shape赋予ShapeDrawable OvalShape ovalShape = new OvalShape(); ShapeDrawable drawable1 = new ShapeDrawable(ovalShape); drawable1.getPaint().setColor(Color.BLUE); drawable1.getPaint().setStyle(Paint.Style.FILL); findViewById(R.id.textView1).setBackgroundDrawable(drawable1); //矩形形状 : shape赋予ShapeDrawable RectShape rectShape = new RectShape(); ShapeDrawable drawable2 = new ShapeDrawable(rectShape); drawable2.getPaint().setColor(Color.RED); drawable2.getPaint().setStyle(Paint.Style.FILL); findViewById(R.id.textView2).setBackgroundDrawable(drawable2); //扇形、扇面形状 : shape赋予ShapeDrawable //顺时针,开始角度30, 扫描的弧度跨度180 ArcShape arcShape = new ArcShape(30, 180); ShapeDrawable drawable4 = new ShapeDrawable(arcShape); drawable4.getPaint().setColor(Color.YELLOW); drawable4.getPaint().setStyle(Paint.Style.FILL); findViewById(R.id.textView4).setBackgroundDrawable(drawable4);
一般作为ImageView的图像来显示
另一个是作为View的背景
自定义Drawable主要就是实现draw方法
setAlpha、setColorFilter、getOpacity也需要重写,但是模板固定
当自定义Drawable有固定大小时(比如绘制一张图片),需要重写getIntrinsicWidth()/getIntrinsicHeight()方法(默认返回-1),会影响到View的wrap_content布局
内部固定大小不等于Drawable的实际区域大小,getBounds能获得实际区域大小
模板代码:
class CustomDrawable(color: Int) : Drawable(){ var mPaint: Paint init { mPaint = Paint(Paint.ANTI_ALIAS_FLAG) mPaint.color = color } override fun draw(canvas: Canvas) { val rect = bounds canvas.drawCircle(rect.exactCenterX(), rect.exactCenterY(), Math.min(rect.exactCenterX(), rect.exactCenterY()), mPaint) } override fun setAlpha(alpha: Int) { mPaint.alpha = alpha invalidateSelf() } override fun setColorFilter(colorFilter: ColorFilter?) { mPaint.colorFilter = colorFilter invalidateSelf() } override fun getOpacity(): Int { //not sure, so be safe return PixelFormat.TRANSLUCENT } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。