Drawable系列简记

前言

慕课网Android中的各种Drawable笔记

Drawable

1.Drawable是一个抽象类,是对可绘制物件的抽象。与View的区别是:没有事件和交互方法。
其子类有BitmapDrawable、LayerDrawable、StateListDrawable、ClipDrawable、TransitionDrawable、InsetDrawable。

BitmapDrawable

1.作用:设置图片缩放,平铺等。
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,设置图片时,src中不能用svg的资源文件,否则会报错。

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="true"
    android:src="@drawable/ic_ll"
    android:tileMode="repeat">

</bitmap>

添加到控件的background或src属性上
3.属性
android:antialias:抗锯齿
android:tileMode:平铺模式
android:dither:抗抖动

4.效果
这里写图片描述

LayerDrawable

1.作用:管理一组drawable,使drawable资源按照列表顺序绘制,列表最后一个drawable绘制在最上层
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,bitmap可改为其他,比如shape

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:left="20dp"
        android:top="20dp">

        <!--这里放置第一张图片-->
        <bitmap android:src="@drawable/ic_ll"/>

    </item>

    <item
        android:left="20dp"
        android:top="20dp">

        <!--这里放置第二张图片-->
        <bitmap android:src="@drawable/ic_location"/>

    </item>

</layer-list>

添加到控件的background或src属性上

3.效果
这里写图片描述

StateListDrawable

1.作用:根据不同的状态提供不同的背景。就是常见的selector。
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,这里以点击事件为例

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="@color/colorPrimary"/>
        </shape>
    </item>

    <!--不设置相当于将android:state_pressed设置成false-->
    <item >
        <shape>
            <solid android:color="@color/colorAccent"/>
        </shape>
    </item>
</selector>

添加到控件的background或src属性上

LevelListDrawable

1.作用:管理一组drawable,每组都设置对应的最大值和最小值,作为选择该组的区间,这样可以根据外部设置的不同值选择不同的drawable
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:drawable="@drawable/ic_lamp_off"
        android:maxLevel="5"
        android:minLevel="1" />

    <item
        android:drawable="@drawable/ic_lamp_on"
        android:maxLevel="10"
        android:minLevel="6" />

</level-list>

添加到控件的background或src属性上

外部调用

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class DrawableActivity extends Activity {
    private Button btnOn;
    private Button btnOff;
    private ImageView ivImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable);
        btnOn = findViewById(R.id.btn_on);
        btnOff = findViewById(R.id.btn_off);
        ivImage = findViewById(R.id.iv_image);
        // 一定要先设置个默认状态,否则将不显示图片,这里默认显示ic_lamp_on
        ivImage.setImageLevel(6);
        btnOff.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 显示ic_lamp_off图片,只要将值设置在1-5
                ivImage.setImageLevel(3);
            }
        });

        btnOn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 显示ic_lamp_on图片,只要将值设置在6-10
                ivImage.setImageLevel(6);
            }
        });
    }

}

3.效果
这里写图片描述

TransitionDrawable

1.作用:是LayerDrawable的子类,不过只负责两层drawable,并提供了一个透明度变化的动画,可以控制从一层drawable过度到另外一层drawable的动画效果。
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/ic_lamp_off"/>

    <item android:drawable="@drawable/ic_lamp_on" />

</transition>

添加到控件的background或src属性上

外部调用

import android.app.Activity;
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class DrawableActivity extends Activity {
    private Button btnOn;
    private Button btnOff;
    private ImageView ivImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable);
        btnOn = findViewById(R.id.btn_on);
        btnOff = findViewById(R.id.btn_off);
        ivImage = findViewById(R.id.iv_image);
        btnOff.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 先获取TransitionDrawable
                TransitionDrawable drawable = (TransitionDrawable) ivImage.getDrawable();
                // 开启过度变化,并设置时长
                drawable.startTransition(5000);
            }
        });

        btnOn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 先获取TransitionDrawable
                TransitionDrawable drawable = (TransitionDrawable) ivImage.getDrawable();
                // 开启反向过度变化,并设置时长
                drawable.reverseTransition(5000);
            }
        });
    }

}

3.效果
这里写图片描述

InsetDrawable

1.作用:表示一个drawable嵌入到另外一个drawable内部,并且在内部留一些间距,这一点很像drawable的padding属性。
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,

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

</inset>

添加到控件的background或src属性上

  <ImageView
        android:id="@+id/iv_image"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="centerInside"
        android:background="@color/colorPrimary"
        android:src="@drawable/inset_bitmap"/>

3.效果
这里写图片描述

ClipDrawable

1.介绍:ClipDrawable是通过设置一个Drawable的当前显示比例来裁剪出另一张Drawable,你可以通过调节这个比例来控制裁剪的宽高,以及裁剪内容占整个容器的权重,通过ClipDrawable的setLevel()方法调节显示比例可以实现类似Progress进度条的效果。ClipDrawable的level值范围在[0,10000],level的值越大裁剪的内容越少,如果level为10000时则完全显示。
2.设置:在资源文件res下创建drawable目录,并创建xxx.xml文件,代码如下,

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/ic_lamp_off"
    android:gravity="right">

</clip>

添加到控件的background或src属性上

3.属性
1、android:drawable;表示该ClipDrawable引用的drawable资源(这个属性必须有)。
2、android:clipOrientation;表示裁剪的方向。horizontal:水平方向,vertical:垂直方向。
3、android:gravity;指定从哪个地方裁剪。必须是下面一个或多个值(多个值之间用“|”分隔)

1.top 将这个对象放在容器的顶部,不改变其大小,当clipOrientation 是”vertical”,从底部(bottom)开始裁剪。
2.bottom 将这个对象放在容器的底部,不改变其大小。当clipOrientation 是 “vertical”,从顶部(top)开始裁剪。
3.left 将这个对象放在容器的左部,不改变其大小。当clipOrientation 是 “horizontal”,从右边(right)开始裁剪。
4.right 将这个对象放在容器的右部,不改变其大小。当clipOrientation 是 “horizontal”,从左边(left)开始裁剪。
5.center_vertical 将对象放在垂直中间,不改变其大小。裁剪的情况和”center“一样。
6.fill_vertical 垂直方向上不发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)
7.center_horizontal 将对象放在水平中间,不改变其大小。裁剪的情况和”center“一样。
8.fill_horizontal 水平方向上不发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)
9.center 将这个对象放在水平垂直坐标的中间,不改变其大小。当clipOrientation 是 “horizontal”裁剪发生在左右。当clipOrientation是”vertical”,裁剪发生在上下。
11.fill 填充整个容器,不会发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)。
12.clip_vertical 额外的选项,它能够把它的容器的上下边界,设置为子对象的上下边缘的裁剪边界。裁剪要基于对象垂直重力设置:如果重力设置为top,则裁剪下边,如果设置为bottom,则裁剪上边,否则则上下两边都要裁剪。
13.clip_horizontal 额外的选项,它能够把它的容器的左右边界,设置为子对象的左右边缘的裁剪边界。裁剪要基于对象垂直重力设置:如果重力设置为right,则裁剪左边,如果设置为left,则裁剪右边,否则则左右两边都要裁剪。
注意:android:gravity需要和android:clipOrientation配合使用,不同的组合,裁剪的效果也不同。

外部调用

import android.app.Activity;
import android.graphics.drawable.ClipDrawable;
import android.os.Bundle;
import android.widget.ImageView;

public class DrawableActivity extends Activity {
    private ImageView ivImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable);

        ivImage = findViewById(R.id.iv_image);
        ClipDrawable drawable = (ClipDrawable) ivImage.getDrawable();
        drawable.setLevel(5000);

    }

}

4.效果
这里写图片描述

自定义Drawable

实现步骤
1.创建一个类并继承Drawable,实现其中的四个方法:draw、setAlpha、setColorFilter、getOpacity,如果需要改变宽和高,需要实现getIntrinsicHeight、getIntrinsicWidth方法。
2.在draw方法实现具体的绘制
3.将drawable设置到ImageView中
代码实现
1.自定义圆形图片Drawable

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

/**
 * 
 * 设置圆形图片
 */

public class MyDrawable extends Drawable {
    private Paint paint;
    private Paint strokePaint;
    private int width;

    /**
     * 通过构造方法传入所需要绘制的图片
     *
     * @param bitmap
     */
    public MyDrawable(Bitmap bitmap) {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint.setShader(bitmapShader);
        strokePaint.setStyle(Paint.Style.STROKE);
        strokePaint.setColor(Color.BLUE);
        width = Math.min(bitmap.getWidth(), bitmap.getHeight());
        // 设置描边
        strokePaint.setStrokeWidth(20);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        // 实现具体的绘制
        int x = width / 2;
        int y = width / 2;
        int radius = width / 2;

        canvas.drawCircle(x, y, radius, paint);
        // 这里radius不能减20
        canvas.drawCircle(x, y, radius - 10, strokePaint);
    }

    @Override
    public void setAlpha(int alpha) {
        paint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        paint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicHeight() {
        return width;
    }

    @Override
    public int getIntrinsicWidth() {
        return width;
    }
}

将Drawable设置到ImageView

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;

import com.lgf.myapplication.widget.MyDrawable;

public class DrawableActivity extends Activity {
    private ImageView ivImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable);

        ivImage = findViewById(R.id.iv_image);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_ly);
        ivImage.setImageDrawable(new MyDrawable(bitmap));

    }

}

效果
这里写图片描述

2.自定义圆角矩形

package com.lgf.myapplication.widget;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

/**
 * 设置圆角图片
 */

public class MyRoundDrawable extends Drawable {
    private Paint paint;
    private Paint strokePaint;
    private Bitmap bitmap;
    private RectF roundBoundsRectF;
    private RectF roundRectF;

    /**
     * 通过构造方法传入所需要绘制的图片
     *
     * @param bitmap
     */
    public MyRoundDrawable(Bitmap bitmap) {
        this.bitmap = bitmap;
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint.setShader(bitmapShader);
        strokePaint.setStyle(Paint.Style.STROKE);
        strokePaint.setColor(Color.BLUE);
        // 设置描边
        strokePaint.setStrokeWidth(20);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        // 实现具体的绘制
        // 30表示圆角弧度
        canvas.drawRoundRect(roundRectF, 30, 30, paint);
        canvas.drawRoundRect(roundBoundsRectF, 30, 30, strokePaint);
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        roundRectF = new RectF(left, top, right, bottom);
        roundBoundsRectF = new RectF(left + 10, top + 10, right - 10, bottom - 10);
    }

    @Override
    public void setAlpha(int alpha) {
        paint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        paint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicWidth() {
        return bitmap.getWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return bitmap.getHeight();
    }
}

效果
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值