六、Drawable

掌握Drawable可以做出一些特殊的效果.

1.Drawable的内部宽高

通过getIntrinsicWidth和getIntrinsicHeight这两个方法可以获取到。并不是所有的Drawable都有内部宽高,比如一张图片所形成的的Drawable,它的内部宽高就是图片的宽高,但是一个颜色所形成的的Drawable,就没有内部宽高的概念。
另外需要注意的是,Drawable的内部宽高不等同于它的大小,一般来说,Drawable是没有大的概念的,当用作View的背景的时候,Drawable会被拉伸至View的同等大小。

2.Drawable的分类

2.1.BitmapDrawable

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:antialias=["true" | "false"]
    android:dither=["true" | "false"]
    android:filter=["true" | "false"]
    android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                      "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                      "center" | "fill" | "clip_vertical" | "clip_horizontal"]
    android:mipMap=["true" | "false"]
    android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />

表示的就是一张图片,在实际的开发中,可以直接引用原始的图片即可,也可以通过xml的方式来描述。
src:图片的资源id

antialias:是否开启图片的抗锯齿,开启后会让图片更加圆滑,同时会在一定的程度上面降低图片的清晰度,但是这个降低的幅度较低以至于可以忽略。因此抗锯齿选项应该开启。

dither:是否开启抖动效果。根据分析,抖动效果应该开启。

filter:是否开启过滤效果。当图片尺寸被拉伸或者压缩的时候,开启过滤效果可以保持较好的显示效果,因此应当开启。

gravity:当图片的尺寸小于容器的尺寸的时候,设置此选项可以对图片进行定位。

mipMap:图片相关的处理技术叫纹理映射,默认值为false,开发中此选项不常用。

tileMode:平铺模式。disabled表示关闭平铺模式,默认值。当开启平铺模式之后gravity属性会被忽略。

repeat表示简单的水平和竖直方向的平铺效果;

mirror表示在水平和竖直方向上的镜面投影效果;

clamp表示图片四周的像素会扩展到周围区域。

2.2.NinePatchDrawable

<?xml version="1.0" encoding="utf-8"?>
<nine-patch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:dither=["true" | "false"] />

xml中的属性和BitmapDrawable中标签的属性是一样的,表示一张.9格式的图片。.9图片可以自动地根据所需的宽/高进行相应的缩放并保证不失真,和BitmapDrawable一样,在实际开发中可以直接引用,实际使用过程中发现bitmap标签也可以使用.9图。

2.3.ShapeDrawable

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape=["rectangle" | "oval" | "line" | "ring"] >
    <corners
        android:radius="integer"
        android:topLeftRadius="integer"
        android:topRightRadius="integer"
        android:bottomLeftRadius="integer"
        android:bottomRightRadius="integer" />
    <gradient
        android:angle="integer"
        android:centerX="integer"
        android:centerY="integer"
        android:centerColor="integer"
        android:endColor="color"
        android:gradientRadius="integer"
        android:startColor="color"
        android:type=["linear" | "radial" | "sweep"]
        android:useLevel=["true" | "false"] />
    <padding
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer" />
    <size
        android:width="integer"
        android:height="integer" />
    <solid
        android:color="color" />
    <stroke
        android:width="integer"
        android:color="color"
        android:dashWidth="integer"
        android:dashGap="integer" />
</shape>

shape:图形的形状,矩形,椭圆,横线,圆环,默认矩形,另外,line和ring这两个选项必须通过stroke指定闲的宽度和颜色等信息。

针对ring这个环状,有5个特殊的属性:
android:innerRadius圆环的内半径,和android:innerRadiusRatio同时存在时,以android:innerRadius为准。
android:innerRadiusRatio内半径占整个Drawable宽度的比例,默认为9。如果为n,那么内半径=宽度/n
android:thickness圆环的厚度,即外半径减去内半径的大小,和android:thicknessRatio同时存在时,以android:thickness为准。
android:thicknessRatio厚度占整个Drawable宽度的比例,默认值为3。如果为n,那么厚度=宽度/n
android:useLevel一般应该使用false,否则有可能无法达到预期的显示效果,除非被当做LevelListDrawable。

corners:表示shape的四个角的角度。只适用于矩形shape,这里的角度指的是圆角的程度用px来表示。

android:radius为四个角同时设定相同的角度,优先级较低,会被其他四个属性覆盖。
android:topLeftRadius设定左上角的角度
android:topRightRadius设定右上角的角度
android:bottomLeftRadius设定左下角的角度
android:bottomRightRadius设定右下角的角度

gradient:与solid标签是互相排斥的,其中solid表示纯色填充,而gradient表示渐变效果。

android:angle渐变的角度。默认为0,其值必须为45的倍数,0表示从左到右,90表示从下到上。
android:centerX渐变的中心点的横坐标
android:centerY渐变的中心点的纵坐标
android:startColor渐变的起始色
android:centerColor渐变的中间色
android:endColor渐变的结束色
android:gradientRadius渐变半径,仅当android:type为radial有效
android:useLevel一般为false,当Drawable作为StateListDrawable使用时为true
android:type渐变的类型,有linear线性渐变,radial径向渐变,sweep扫描线渐变三种,默认为线性渐变。

solid:这个表示纯色填充,通过color即可指定shape中填充的颜色。

stroke:shape的描边。
android:width描边的宽度,越大则shape的边缘线就会看起来约粗
android:color描边的颜色
android:dashWidth组成虚线的线段的宽度
android:dashGap组成虚线的线段之间的间隔,间隔越大看起来空隙就越大
注意:如果android:dashWidth和android:dashGap有任何一个为0,那么虚线效果将不能生效

padding:表示空白,但是它表示的不是shape的空白,而是包含它的view的空白。

size:shape的大小,属性android:width,android:height。

表示shape的固有大小,一般来说不是shape最终显示的大小,shape没有宽高的概念,作为view的背景会自适应view的宽高。Drawable的两个方法getIntrinsicWidth和getIntrinsicHeight表示的是Drawable的固有宽高,对于有些Drawable比如图片来说,它的固有宽高就是图片的尺寸,对于shape来说,默认情况下,它是没有固有宽高这个概念的,这个时候那两个方法就会返回-1,但是如果通过size标签设置宽高信息,shape就有了所谓的固有宽高。

总结来说,size标签设置的宽高就是ShapeDrawable的固有宽高,但是作为view的背景时,shape还会被拉伸或者缩小为view的大小。

2.4.LayerDrawable

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</layer-list>

表示一种层次化的Drawable集合,通过将不同的Drawable放置在不同的层上面从而达到一种叠加后的效果。这些属性分别表示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>

2.5.StateListDrawable

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:constantSize=["true" | "false"]
    android:dither=["true" | "false"]
    android:variablePadding=["true" | "false"] >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:state_pressed=["true" | "false"]
        android:state_focused=["true" | "false"]
        android:state_hovered=["true" | "false"]
        android:state_selected=["true" | "false"]
        android:state_checkable=["true" | "false"]
        android:state_checked=["true" | "false"]
        android:state_enabled=["true" | "false"]
        android:state_activated=["true" | "false"]
        android:state_window_focused=["true" | "false"] />
</selector>

表示Drawable集合,每个Drawable对应着View的一种状态,这样系统就会根据View的状态来选择合适的Drawable。
属性:
android:constantSizeDrawable的固有大小是否不随着其状态的改变而改变,默认值为false。
android:dither抖动效果是否开启,默认为true
android:variablePaddingDrawable的padding表示是否随着状态的改变而改变,默认false。
item标签表示一个具体的Drawable。

2.6.LevelListDrawable

<?xml version="1.0" encoding="utf-8"?>
<level-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@drawable/drawable_resource"
        android:maxLevel="integer"
        android:minLevel="integer" />
</level-list>

表示Drawable集合,集合中的每个Drawable都有一个等级的概念,根据不同的等级,Drawable会切换为对应的Drawable。
作为View的背景的时候,可以通过Drawable的setLevel方法来设置不同的等级从而切换具体的Drawable,被用作ImageView的前景时,可以通过ImageView的setImageLevel方法来切换Drawable。范围0-10000。

2.7.TransitionDrawable

<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</transition>

表示两个Drawable之间的淡入淡出效果。
可以使用它的startTransition和reverseTransition方法来实现淡入淡出的效果以及它的逆过程。

2.8.InsetDrawable

<?xml version="1.0" encoding="utf-8"?>
<inset
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:insetTop="dimension"
    android:insetRight="dimension"
    android:insetBottom="dimension"
    android:insetLeft="dimension" />

可以将其他Drawable内嵌到自己当中,并可以在四周留出一定的间距。当一个view希望自己的背景比自己的实际区域小的时候,可以采用它实现。

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetBottom="15dp"
    android:insetLeft="15dp"
    android:insetRight="15dp"
    android:insetTop="15dp" >
    <shape android:shape="rectangle" >
        <solid android:color="#ff0000" />
    </shape>
</inset>

shape距离view的边界15dp。

2.9.ScaleDrawable

<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                          "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                          "center" | "fill" | "clip_vertical" | "clip_horizontal"]
    android:scaleHeight="percentage"
    android:scaleWidth="percentage" />

可以根据自己的等级level将指定的Drawable缩放到一定的比例。android:scaleHeight,android:scaleWidth分别表示对指定Drawable宽和高的缩放比例,以百分比的形式表示。想要ScaleDrawable可见,需要等级不能为0。范围0-10000。

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/image_bg"
    android:scaleHeight="70%"
    android:scaleWidth="70%"
    android:scaleGravity="center" />
View testScale = findViewById(R.id.test_scale);
ScaleDrawable testScaleDrawable = (ScaleDrawable) testScale.getBackground();
testScaleDrawable.setLevel(10);

2.10.ClipDrawable

<?xml version="1.0" encoding="utf-8"?>
<clip
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:clipOrientation=["horizontal" | "vertical"]
    android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                     "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                     "center" | "fill" | "clip_vertical" | "clip_horizontal"] />

可以根据自己的等级level来裁剪另一个Drawable。

将一张图片从上到下裁剪:

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="vertical"
    android:drawable="@drawable/image_bg"
    android:gravity="bottom" />
ImageView testClip = (ImageView) findViewById(R.id.test_clip);
ClipDrawable testClipDrawable = (ClipDrawable) testClip.getDrawable();
testClipDrawable.setLevel(8000);

等级设置为8000表示,裁剪2000,在顶部裁掉20%。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现这个功能,你需要做以下几步: 1. 在布局文件中添加两个ImageView,一个用于显示背景,另一个用于显示指针。 2. 创建一个旋转动画,用于旋转指针。 3. 编写代码计算旋转角度,确保指针指向分之一概率的位置。 4. 在代码中启动旋转动画,使指针旋转到计算出的角度。 下面是一个简单的示例代码: 1. 布局文件 ``` <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/img_bg" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/bg" /> <ImageView android:id="@+id/img_pointer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/pointer" android:layout_centerInParent="true" /> </RelativeLayout> ``` 2. 创建旋转动画 ``` private void createRotateAnimation() { RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setDuration(2000); rotateAnimation.setFillAfter(true); pointerImg.setAnimation(rotateAnimation); } ``` 3. 计算旋转角度 ``` private float calculateAngle() { Random random = new Random(); int randomInt = random.nextInt(6); // 生成 0~5 的随机数 float baseAngle = 60 * randomInt; // 每个区域大小为 60 度 float offsetAngle = random.nextFloat() * 60; // 偏移角度,确保指针指向随机位置 return baseAngle + offsetAngle; } ``` 4. 启动旋转动画 ``` private void startRotateAnimation() { float angle = calculateAngle(); RotateAnimation rotateAnimation = new RotateAnimation(0, angle, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setDuration(2000); rotateAnimation.setFillAfter(true); pointerImg.startAnimation(rotateAnimation); } ``` 这样就实现了一个简单的分之一概率转盘。注意,这只是一个示例,实际应用中还需要进行更多的优化和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值