Drawable简介

Drawable是Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP。相比于View,我们并不需要去考虑如何measure、layout,仅仅只要去考虑如何draw(canavs)。
Though usually not visible to the application, Drawables may take a variety of forms 形式: Bitmap: the simplest Drawable, a PNG or JPEG image. Nine Patch: an extension 引申、扩展 to the PNG format allows it to specify 描述 information about how to stretch 延伸、拉长 it and place things inside of it. Shape: contains simple drawing commands 命令 instead of a raw 原始 bitmap, allowing it to resize 调整大小 better in some cases. Layers: a compound 合成的 drawable, which draws multiple 多重的、复杂的 underlying 底层的 drawables on top of each other. States: a compound drawable that selects one of a set of drawables based on its state. Levels: a compound drawable that selects one of a set of drawables based on its level. Scale: a compound drawable with a single 单一的 child drawable, whose overall 全部的 size is modified 可改变的 based on the current level.

Drawable在xml中的标签及其对应的实体类如下:

Drawable和Bitmap的区别

A bitmap is a Drawable. A Drawable is not necessarily 不一定是 a bitmap. Like all thumbs 拇指 are fingers 手指 but not all fingers are thumbs.

        Bitmap,代表一个位图图像,Android支持三种格式的位图图像:.png (preferred 图片优先),.jpg (acceptable 也可以 但是效果没有.png好), .gif (discouraged 支持最差),当然编码器也有很多,如RGB565、RGB888。作为一种逐像素的显示方式,其执行效率高,但是缺点也很明显,存储效率低。
        另外要注意,在构建应用的时候,Bitmap文件可能会被appt工具压缩自动优化为无损图像。例如,一个真彩色PNG,不需要超过256的颜色可以被转换成一个8位PNG和调色板。这将导致一个图像质量相同,但这需要更少的内存。所以要意识到,在drawable目录中图像的二进制文件在构建程序时可能被改变。如果你打算读一个图像作为字节流并将它转换成一个位图,把你的图片放在在res /raw/文件夹里,在那里他们不会被优化。

两者对比:
对比项  显示清晰度 占用内存 支持缩放 支持色相色差调整 支持旋转 支持透明色 绘制速度 支持像素操作
Bitmap        相同          大           是                 是                    是            是              慢              是
Drawable    相同          小           是                 否                    是            是              快              否
Drawable在内存占用和绘制速度这两个非常关键的点上胜过Bitmap,但是不支持色相色差调整,不支持像素操作。

设置Drawable时的注意事项

在代码中设置Drawable有两种方式
        Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
        rb.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
        drawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
        rb.setCompoundDrawables(null, drawable, null, null);

1、setCompoundDrawables方法
        Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables must already have had setBounds(Rect) called.
        这个方法要先给Drawable设置drawable.setBounds(left, top, right, bottom),即组件在容器X、Y轴上的起点(相对自身),长度、高度。
        如:drawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
        若没设置,则setCompoundDrawables后不会显示图片!
        好处是可以打破原有的大小及比例自由设置图片大小。

2、setCompoundDrawablesWithIntrinsicBounds()方法
        Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables' bounds will be set to their intrinsic bounds.
        可以在上、下、左、右设置图标,如果不想在某个地方显示,则设置为null。图标的宽高将会设置为固有宽高。不过只能在高版本中才能使用此方法。


自定义圆形Drawabe

public class CircleImageDrawable extends Drawable {
    private Paint mPaint;
    private int mWidth;
    private Bitmap mBitmap;
    public CircleImageDrawable(Bitmap bitmap) {
        mBitmap = bitmap;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        //BitmapShader通过设置给mPaint,然后用这个mPaint绘图时,就会根据你设置的TileMode,对绘制区域进行着色
        mPaint.setShader(new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP));
        mWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());
    }
    @Override
    public void draw(Canvas canvas) {//必须重写的方法
        canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mPaint);
    }
    @Override
    public void setAlpha(int alpha) {//必须重写的方法
        mPaint.setAlpha(alpha);
    }
    @Override
    public void setColorFilter(ColorFilter cf) {//必须重写的方法
        mPaint.setColorFilter(cf);
    }
    @Override
    public int getOpacity() {//必须重写的方法
        return PixelFormat.TRANSLUCENT;
    }
    @Override
    public int getIntrinsicWidth() {//在View使用wrap_content的时候,提供Drawable的尺寸
        return mWidth;
    }
    @Override
    public int getIntrinsicHeight() {
        return mWidth;
    }
}

public class CircleImageDrawableActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
        ((ImageView) findViewById(R.id.id_one)).setImageDrawable(new CircleImageDrawable(bitmap));//wrap_content
        ((ImageView) findViewById(R.id.id_two)).setImageDrawable(new CircleImageDrawable(bitmap));//120dp
    }
}

自定义圆角矩形Drawabe

public class RoundImageDrawable extends Drawable {
    private Paint mPaint;
    private Bitmap mBitmap;
    private RectF rectF;
    private float rx, ry;
    public RoundImageDrawable(Bitmap bitmap, float rx, float ry) {
        mBitmap = bitmap;
        this.rx = rx;
        this.ry = ry;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP));
    }
    @Override
    public void setBounds(int left, int top, int right, int bottom) {//设置绘制的范围
        super.setBounds(left, top, right, bottom);
        rectF = new RectF(left, top, right, bottom);
    }
    @Override
    public void draw(Canvas canvas) {
        canvas.drawRoundRect(rectF, rx, ry, mPaint);
    }
    @Override
    public int getIntrinsicWidth() {
        return mBitmap.getWidth();
    }
    @Override
    public int getIntrinsicHeight() {
        return mBitmap.getHeight();
    }
    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }
    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
    }
    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}

public class RoundImageDrawableActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
        ((ImageView) findViewById(R.id.id_one)).setImageDrawable(new RoundImageDrawable(bitmap, 60, 60));
        ((ImageView) findViewById(R.id.id_two)).setImageDrawable(new RoundImageDrawable(bitmap, 30, 30));
    }
}

自定义Drawable的状态

1、自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MessageStatus">
        <attr name="state_message_readed" format="boolean" />
    </declare-styleable>
</resources>

2、自定义View
public class MessageListItem extends RelativeLayout {
    private static final int[] STATE_MESSAGE_READED = { R.attr.state_message_readed };
    private boolean mMessgeReaded = false;
    public MessageListItem(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public void setMessageReaded(boolean readed) {
        if (this.mMessgeReaded != readed) {
            mMessgeReaded = readed;
            refreshDrawableState();
        }
    }
    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        //在mMessgeReaded=true的情况下,把我们自定义的状态添加进去
        if (mMessgeReaded) {
            int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            mergeDrawableStates(drawableState, STATE_MESSAGE_READED);
            return drawableState;
        }
        return super.onCreateDrawableState(extraSpace);
    }
}

3、布局中使用自定义View
<com.bqt.drawable.view.MessageListItem xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="@drawable/message_item_bg" >
    <ImageView
        android:id="@+id/icon"
        android:layout_width="30dp"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:duplicateParentState="true"
        android:src="@drawable/message_item_icon_bg" />
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@id/icon" />
</com.bqt.drawable.view.MessageListItem>

4、代码中设置此View的状态
public class CustomStateDrawableActivity extends ListActivity {
    private MessageBean[] messages = new MessageBean[10];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        for (int i = 0; i < messages.length; i++) {
            messages[i] = new MessageBean(i + "", true & (i == 1 || i == 5 || i == 6 || i == 8));
        }
        getListView().setAdapter(new ArrayAdapter<MessageBean>(this, -1, messages) {
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if (convertView == null) {
                    convertView = LayoutInflater.from(CustomStateDrawableActivity.this).inflate(R.layout.item_msg_list, parent, false);
                }
                ((TextView) convertView.findViewById(R.id.text)).setText(getItem(position).message);
                ((MessageListItem) convertView).setMessageReaded(getItem(position).readed);
                return convertView;
            }
        });
    }
}

Drawable与Bitmap 自定义的更多相关文章

  1. Android Drawable、Bitmap、byte[]之间的转换

    转自http://blog.csdn.net/june5253/article/details/7826597 1.Bitmap-->Drawable Bitmap drawable2Bitma ...

  2. Drawable和Bitmap区别

    Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565.RGB888.作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低.我们理解为一种存储对象比较好 ...

  3. 获取应用图标,Drawable 转bitmap

    获取应用图标: PackageManager p = context.getPackageManager(); Drawable draw=null; ApplicationInfo info; tr ...

  4. 简单谈谈Resource,Drawable和Bitmap之间的转换

    一直接触这些东西,还是归个类整理一下比较好. Resource -> Drawable Drawable draw1 = this.getResources().getDrawable(R.dr ...

  5. android 获取资源文件 r.drawable中的图片转换为drawable、bitmap

    1.R-Drawable Resources resources = mContext.getResources(); Drawable drawable = resources.getDrawabl ...

  6. Android -- Drawable与Bitmap测试

    Drawable                                                                                 以下这个是测试加载10 ...

  7. Drawable和Bitmap转换

    一.Bitmap转Drawable Bitmap mBitMap=getYourBitMap(); //getYourBitMap()是你获取BitMap的方法 BitmapDrawable mBit ...

  8. Drawable、Bitmap、byte[]之间的转换

    android在处理一写图片资源的时候,会进行一些类型的转换: 1 Drawable → Bitmap 的简单方法 ((BitmapDrawable)res.getDrawable(R.drawabl ...

  9. Drawable与Bitmap(转)

    Drawable                                                                                 以下这个是测试加载10 ...

随机推荐

  1. jQuery旋转插件

    jQuery旋转插件,支持Internet Explorer 6.0 + .Firefox 2.0.Safari 3.Opera 9.Google Chrome,高级浏览器下使用Transform,低 ...

  2. 武汉科技大学ACM:1004: 华科版C语言程序设计教程(第二版)习题5.6

    Problem Description 这天老师又给小豪出了一道题目:给你三根长度分别为a,b,c的火柴,让你计算这三跟火柴能组成的三角形的面积. Input 输入每行包括三个数a,b,c. Outp ...

  3. 高放的c++学习笔记之函数基础

    局部变量 函数里面的局部变量有普通的局部变量和局部静态变量两种. 普通局部变量变量就是正常定义在函数体内部的变量,如果返回局部变量的地址,以便于函数调用结束后还继续访问此变量的话,编译器会报warni ...

  4. C++ Primer 5th 第9章 顺序容器

    练习9.1:对于下面的程序任务,vector.deque和list哪种容器最为适合?解释你的选择的理由.如果没有哪一种容器优于其他容器,也请解释理由.(a) 读取固定数量的单词,将它们按字典序插入到容 ...

  5. 制作PHP安装程序的原理和步骤56

    制作PHP安装程序的原理和步骤56 1.制作PHP安装程序的原理和步骤检查目录或文件的权限----修改或填加配置文件---检查配置文件正 确性---导入数据库----锁定或删除安装文件 原理: 其实P ...

  6. Nginx源码研究一:NGINX模块启动

    Nginx 是一个轻量级,但是高性能的 HTTP 和 代理 服务器,也是一个 IMAP/POP3/SMTP代理服务器. 它的第一个版本0.1.0是由俄罗斯的工程师Igor Sysoev与2004年10 ...

  7. 为Linux服务器伪装上Windows系统假象

    网络上的计算机很容易被黑客利用工具或其它手段进行扫描,以寻找系统中的漏洞,然后再针对漏洞进行攻击. 通过伪装Linux系统,给黑客设置系统假象,可以加大黑客对系统的分析难度,引诱他们步入歧途,从而进一 ...

  8. jdk-map-hashMap

    关于java中的HashMap,我们在项目中经常使用到,但是我们的场景是否使用对了呢? 下面分为四个部分来阐述我的HashMap的理解 1.为什么要使用hashMap? 在项目中,需求的实现需要使用到 ...

  9. Java was started but returned exit code=13

    安装Eclipse(32位)后打开报错:Java was started but returned exit code=13 解决方法: 1,首先我查看了我当前安装的JDK版本,发现是64位的: 2, ...

  10. 07 - 删除vtkDataObject中的SetExtentTranslator 和 GetExtentTranslator方法 VTK 6.0 迁移

    VTK6 引入了许多不兼容的变.其中之一是删除vtkDataObject中所有有关管道的方法.其中的两个方法就是SetExtentTranslator() 和 GetExtentTranslator( ...