Android中Drawable

**Lroid是一款基于Anddroid平台开发的app, 是一款旨在提高刚想要入行Android系统开发(但已经具备Java语言基础)或者已经开始工作一段时间(但已经具备Java语言基础)想要进一步提高自己能力的app。lroid是以当下流行的MVP为架构,网络通信模块采用retrofit 2.0。里面还包括了RxJava,Dagger2等很热门的应用框架。为了更加接近现实常用的app,而不是一味的讲解Android开发知识点,本软件整合了一些内容来填充框架。
https://item.taobao.com/item.htm?id=541493148052**

在Android中有这样一个类它有点像Bitmap,但却和Bitmap有着本质的区别,那就是——Drawable。我们先来看一下官方文档对它的描述吧。

A Drawable is a general abstraction for “something that can be drawn.”
Most often you will deal with Drawable as the type of resource
retrieved for drawing things to the screen; the Drawable class
provides a generic API for dealing with an underlying visual resource
that may take a variety of forms. Unlike a {@link android.view.View},
a Drawable does not have any facility to receive events or otherwise
interact with the user.

大体意思就是,可以用来画一些东东的东西。
好,让我们看看今天主要学习它哪些地方吧:

  1. Drawable和Bitmap的区别以及两者的互相转换。
  2. Drawable的基本用法。
  3. Drawable的高级用法。

一、Drawable和Bitmap的区别以及两者的互相转换。
Bitmap大家应该都挺熟悉的,描述的是位图,用于图的处理。
我们先来看看Bitmap如何转换成Drawable,这个转换还是比较简单的,Google给我们提供了一个很方便的类——BitmapDrawable。我们只需将一个Bitmap封装到BitmapDrawable就可以得到Drawable对象,具体代码:

public Drawable bitmapToDrawable(Bitmap bitmap){
        Drawable drawable = new BitmapDrawable(getResources(),bitmap);
        return drawable;
    }

下面看看如何将一个Drawable对象转换成Bitmap对象,这个有点复杂,具体代码如下:

public Bitmap drawableToBitmap(Drawable drawable){
        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width,height,drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0,0,width,height);
        drawable.draw(canvas);
        return bitmap;
    }

代码其实还是挺好理解的,创建一个画布,通过Drawable的draw()方法,把图像信息封装到Bitmap中,就可以得到Bitmap对象。
然后就可以通过ImageView的setImageBitmap(Bitmap bitmap)方法和setImageDrawable(Drawable drawable)方法来展示图片。
好,明白了Drawable和Bitmap的关系,下面让我来看看Drawable的基本用法。
二、Drawable的基本用法。
先来看一张图:
这里写图片描述
是不是有很多我们经常通过XML用到的标签。是的,每一个标签都对应了一个Drawable类,以我们最常用的Shape来说,通过XML我们会这样书写:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:bottomLeftRadius="8dp"
        android:bottomRightRadius="8dp"
        android:topLeftRadius="8dp"
        android:topRightRadius="8dp" />
    <stroke
        android:width="1dp"
        android:color="#f00" />

    <solid android:color="#f00"/>
</shape>

效果如下:
这里写图片描述
好,我们通过代码来实现上述效果:
注:标签Shape对于的Java类不是ShapeDrawable,而是GradientDrawable类,千万不要搞错了

 GradientDrawable gradientDrawable = new GradientDrawable();
        gradientDrawable.setCornerRadius(8.0f);
        gradientDrawable.setColor(Color.RED);
        gradientDrawable.setStroke(1,Color.RED);

效果和上面是一样的,是不是觉得用代码控制更简单呢,短短几行代码,就可以实现相同的效果。
好,其他的Drawable类型,大家可以自己亲自动手尝试用代码如何现实XML现实的效果,我就不一一在这介绍了。
下面我们来看一个比较综合的效果,也是开发中一个常见的效果,在iOS比较常见,效果图如下:
这里写图片描述
仿照QQ首页顶部栏。
先来说一下我们的实现思路,方案还是有很多种的:
1,RadioGroup+RadioButton的方式
2,普通布局(LinearLayout或者RelativeLayout)+Button的方式
在这里我们用第一方案,原因是第二中方法我们得自己判断互斥逻辑,比较麻烦,通过第一中方案,就可以直接使用系统已经实现好的逻辑。我们只需要关心的就是如何改变背景而已。
好,具体布局如下:

 <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:padding="10dp"
        android:background="#990000ff"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/id_left_radio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:button="@null"
            android:background="@drawable/left_radio_bg"
            android:textColor="#f00"
            android:padding="8dp"
            android:text="消息"/>

        <RadioButton
            android:id="@+id/id_right_radio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:button="@null"
            android:background="@drawable/right_radio_bg"
            android:textColor="#f00"
            android:padding="8dp"
            android:text="语音"/>

    </RadioGroup>

左边RadioButton的背景实现如下:

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

    <item android:state_checked="true" android:drawable="@drawable/left_checked_bg"></item>

    <item android:state_checked="false" android:drawable="@drawable/left_unchecked_bg"></item>

</selector>

checked状态背景:

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

    <corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp"></corners>

    <solid android:color="#fff"></solid>

    <stroke android:width="1dp" android:color="#fff"></stroke>

</shape>

unchecked状态背景如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp"></corners>

    <solid android:color="@android:color/transparent"></solid>

    <stroke android:width="1dp" android:color="#fff"></stroke>
</shape>

右边的就不具体把代码贴出来了,就是left换成right而已。
这样我们就实现了上图的效果,效果还是挺赞的。是不是很简单呢,嘿嘿,我们来看看用代码如何实现这样的效果。
还是左边效果:

StateListDrawable stateListDrawable = new StateListDrawable();
        GradientDrawable checkedDrawable = new GradientDrawable();
        checkedDrawable.setColor(Color.WHITE);
        checkedDrawable.setStroke(2,Color.WHITE);
        checkedDrawable.setCornerRadii(new float[]{
                //1、2表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角
                8.0f,
                8.0f,
                0.0f,
                0.0f,
                0.0f,
                0.0f,
                8.0f,
                8.0f
        });
        stateListDrawable.addState(new int[]{android.R.attr.state_checked},checkedDrawable);
        GradientDrawable unCheckedDrawable = new GradientDrawable();
        unCheckedDrawable.setColor(Color.TRANSPARENT);
        unCheckedDrawable.setStroke(2,Color.WHITE);
        unCheckedDrawable.setCornerRadii(new float[]{
                //1、2表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角
                8.0f,
                8.0f,
                0.0f,
                0.0f,
                0.0f,
                0.0f,
                8.0f,
                8.0f
        });
        stateListDrawable.addState(new int[]{ - android.R.attr.state_checked },unCheckedDrawable);

这样我们也就实现了XML实现的效果。需要注意几点:
1,setCornerRadii()方法中各个参数代表的含义。代码中已经标明。
2,checked状态和unchecked状态如何用代码实现。
至此,我们这个小例子就通过两种不同的方式实现了,在实际开发中,你可以根据个人喜好自由选择,各有利弊,我喜好代码~
下面我们再来看一个小例子,也是开发中比较常用的,就是数量指示器,效果如下:
这里写图片描述
一般我们看着这样的效果都会找美工要一个背景图,或者自己自定义一个View来实现这样的效果,下面我们就通过Drawable来看看如何实现这样的效果,同样,我们先来看一下通过XML如何实现具体代码如下:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#f00" />
    <padding
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp"
        android:top="1dp" />
    <solid android:color="#f00" />
    <stroke
        android:width="1dp"
        android:color="@android:color/white" />
    <size
        android:width="15dp"
        android:height="15dp" />

</shape>

需要注意几点:
1、android:shape=”oval”属性值,默认为rectangle。
2、size标签
其他的都是平常用的,没什么好说的,再来看一下通过代码如何实现:

 GradientDrawable gradientDrawable = new GradientDrawable();
        gradientDrawable.setShape(GradientDrawable.OVAL);
        gradientDrawable.setStroke(2,Color.WHITE);
        gradientDrawable.setColor(Color.RED);
        gradientDrawable.setSize(30,30);

效果和XML一样。
三、 Drawable的高级用法。
接触过Android开发的人,都知道我们可以自定义一个View来实现一些特效,那么我们可不可以自定义一个Drawable呢,答案当然是可以的,下面我们来看看如何自定义一个Drawable。还是以实例为主我们来实现一个圆形图片,要想实现圆形图片方法有几种一般都是自定义ImageView重写onDraw,其实用Drawable也可以的。先看效果图:
这里写图片描述
代码:

public class CircleDrawable extends Drawable {

    private Paint mPaint;
    private int mRadius;

    public CircleDrawable(Bitmap bitmap){
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setShader(shader);
        mRadius = Math.min(bitmap.getWidth(),bitmap.getHeight()) /2;
    }

    @Override
    public int getIntrinsicHeight() {
        return mRadius * 2 ;
    }

    @Override
    public int getIntrinsicWidth() {
        return mRadius * 2;
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawCircle(mRadius,mRadius,mRadius,mPaint);
    }

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

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

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

好,对于Drawable的高级用法就先介绍这一个,还有一些常用的,等以后再慢慢介绍。主要是基本用法,希望大家都能掌握了,今后用到了可以运用自如。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值