博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 图像绘制之 Drawable的各种用法
阅读量:4100 次
发布时间:2019-05-25

本文共 9527 字,大约阅读时间需要 31 分钟。

Drawable的实现类

官网上查看Drawable 的实现类,如ShapeDrawable,BitmapDrawable,ClipDrawable,RoundBitmapDrawable,StateListDrawableRoateDrawable。我们今天就是大致介绍一下比较常用的类。Drawable 是一种媒介,它可以把内容绘制到 Canvas 上。

GradientDrawable

一个创建图形的 Drawable,图形包括直线(line),

椭圆(oval),圆形(oval,当椭圆的宽高相等的时候就是圆形),矩形(rectangle),圆环(ring)。GradientDrawable
它在 XML 文件中对应的根节点为<Shape>

**下面是shape里一些相关属性:**
Android:shape=["rectangle" | "oval" | "line" | "ring"]其中 rectagle 矩形,oval 椭圆,line 水平直线,ring 环形**
标签中 子节点的常用属性:**
渐变:Android:startColor 起始颜色 Android:endColor 结束颜色 Android:angle 渐变角度,0从左到右,90表示从下到上,数值为45的整数倍,默认为0; Android:type 渐变的样式 liner线性渐变 radial环形渐变 sweep
内部填充Android:color
描边Android:width 描边的宽度 Android:color 描边的颜色 Android:dashWidth表示'-'横线的宽度 Android:dashGap 表示'-'横线之间的距离
圆角Android:radius 圆角的半径 值越大角越圆 Android:topRightRadius 右上圆角半径 Android:bottomLeftRadius 右下圆角角半径 Android:topLeftRadius 左上圆角半径 Android:bottomRightRadius 左下圆角半径
边界填充android:bottom="1.0dip" 底部填充 android:left="1.0dip" 左边填充 android:right="1.0dip" 右边填充 android:top="0.0dip" 上面填充
根据不同的选定状态来定义不同的现实效果> 分为四大属性:> android:state_selected 是否选中> android:state_focused 是否获得焦点> android:state_pressed 是否按压> android:state_enabled 是否设置是否响应事件,指所有事件 另: android:state_window_focused> 默认时的背景图片 引用位置:res/drawable/文件的名称.xml

直线

虚线

在这里插入图片描述

椭圆或者圆形

在这里插入图片描述

如果不用 Stroke( 描边,对应 Paint.STROKE ),而用Solid (填充,对应 Paint.FILL),会出现实心圆形。

矩形

圆环

  1. 这里要说下这个 useLevel, 只有在 LevelListDrawable 中才设置 true,这里要设置
    false,否则显示不出来。
  2. 其实 GradientDrawable 或者说是 ShapeDrawable 的绘制原理就是利用 Canvas.drawCircle() ,Canvas.drawRect() 等等方法(Canvas 我将在后面的文章介绍)。

LayerListDrawable

图层列表,就像我们平时把一张照片放在另外一张照片上,最后的照片在最上面。 LayerListDrawable 就是这样设计的。

StateListDrawable

LevelListDrawable

经典案例:WiFi图标

maxLevel = 0 就是默认图片,看下默认效果

在这里插入图片描述

private static int i = 1;    public void onClickWifi(View view) {
ImageView imageView = (ImageView) findViewById(R.id.wifi_image); imageView.getBackground().setLevel(i++ % 10); }

ColorDrawable

ColorDrawable colorDrawable = new ColorDrawable(Color.RED);imageView.setBackground(colorDrawable);

RoundedBitmapDrawable

其实这个名字应该叫做 圆角图片,它是设置图片四个角的圆形半径。当图片是矩形的时候,就有四个圆角,再特殊一点,如果图片是正方形,正好圆角的半径为正方形边长的一半,那么它就是一个圆。

RoundedBitmapDrawable roundedBitmapDrawable2 =                RoundedBitmapDrawableFactory.create(getResources(),                        BitmapFactory.decodeResource(getResources(),R.mipmap.image1));        //roundedBitmapDrawable2.setCornerRadius(150);  //设置圆角为150度        roundedBitmapDrawable2.setCircular(true);//设置为圆形        roundedBitmapDrawable2.setBounds(10,10,10,10);        im01.setImageDrawable(roundedBitmapDrawable2);

有时候我们如果用的图片过大,就需要截取需要的哪一部分成正方形(矩形),然后生成圆形图片。 图片就会变形

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_5);        // 创建 600*600 正方形 Bitmap,截取头像部分        Bitmap newBitmap = Bitmap.createBitmap(bitmap,                bitmap.getWidth() / 2 - 600 / 2, //x                100,// y                600,//width                600//height        );        // 回收没有用的 bitmap        bitmap.recycle();        RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), newBitmap);        roundedBitmapDrawable.setCornerRadius(newBitmap.getWidth() / 2);        imageView.setImageDrawable(roundedBitmapDrawable);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.image3);        int height = bitmap.getHeight();//图片的高 1200        int width = bitmap.getWidth();//图片的宽 1920        mTextView.setText("height:"+height+"width:"+width);        //创建800*800的正方形Bitmap        /*        @param source 需要裁剪的bitmap        @param x 裁剪x点起始坐标(横向)        @param y 裁剪y点起始坐标(纵向)        @param width 裁剪后,新生成的bitmap的宽度        @param height 裁剪后,新生成的bitmap的高度        * */        Bitmap newBitmap = Bitmap.createBitmap(          bitmap,bitmap.getWidth() / 2-600/2,                50,                800,                800        );        //回收掉没用的bitmap        bitmap.recycle();        RoundedBitmapDrawable roundedBitmapDrawable =                RoundedBitmapDrawableFactory.create(getResources(),newBitmap);        roundedBitmapDrawable.setCornerRadius(newBitmap.getWidth()/2);//自己计算圆角度        //roundedBitmapDrawable.setCircular(true);//设置为圆形        im01.setImageDrawable(roundedBitmapDrawable);

不同大小的图片,需要裁减的位置也不一样,才能完成完美的图片效果,需要搞一个算法(。。。)

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.image2);        int height = bitmap.getHeight();//图片的高 1000        int width = bitmap.getWidth();//图片的宽 993        mTextView.setText("height:"+height+"width:"+width);        //创建800*800的正方形Bitmap        /*        @param source 需要裁剪的bitmap        @param x 裁剪x点起始坐标(横向)        @param y 裁剪y点起始坐标(纵向)        @param width 裁剪后,新生成的bitmap的宽度        @param height 裁剪后,新生成的bitmap的高度        * */        Bitmap newBitmap = Bitmap.createBitmap(                //x + width must be <= bitmap.width()          bitmap,bitmap.getWidth() / 2,                0,                350,                350        );        //回收掉没用的bitmap        bitmap.recycle();
Bitmap.Config ARGB_4444:每个像素占四位,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位 Bitmap.Config ARGB_8888:每个像素占四位,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位Bitmap.Config RGB_565:每个像素占四位,即R=5,G=6,B=5,没有透明度,那么一个像素点占5+6+5=16位Bitmap.Config ALPHA_8:每个像素占四位,只有透明度,没有颜色。

一般情况下我们都是使用的ARGB_8888,由此可知它是最占内存的,因为一个像素占32位,8位=1字节,所以一个像素占4字节的内存。假设有一张480x800的图片,如果格式为ARGB_8888,那么将会占用1500KB的内存

/*    * 使用RoundedBitmapDrawable,图片过大,系统会利用矩阵对我们的图片进行缩放处理,    * 系统将图片缩放成了正方形,所以图片里的东西看起来有点变形,我们利用代码加工图片,    * RoundedBitmapDrawable需要正方形,我们就给他正方形    * */    private Bitmap createRectBitmap(Bitmap bitmap){
int oldHeight = bitmap.getHeight();//原图高度 int oldWidth = bitmap.getWidth();//原图宽度 int borderWidth = 20 ; //边框宽度 //转换为正方形的宽高 取最小 int widthOrHeight = Math.min(oldHeight,oldWidth); //最后的宽高 需要加上边框的宽度 int newBitmapWH = widthOrHeight + borderWidth; Bitmap newBitmap = Bitmap.createBitmap(newBitmapWH,newBitmapWH,Bitmap.Config.ARGB_8888); //画布 Canvas canvas = new Canvas(newBitmap); //画布定义起始点坐标 (x,y)x:-700: y:20 int x = borderWidth + widthOrHeight - oldWidth; int y = borderWidth + widthOrHeight - oldHeight; Log.e("x:"+x,"y:"+y); //裁剪后图像,注意X,Y要除以2 来进行一个中心裁剪 canvas.drawBitmap(bitmap, x/2, y/2, null); //画布抗锯齿 canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG)); Paint borderPaint = new Paint(); borderPaint.setStyle(Paint.Style.STROKE);//画笔mode borderPaint.setStrokeWidth(borderWidth);//画笔宽度 borderPaint.setAntiAlias(true);//抗锯齿 borderPaint.setFilterBitmap(true);//抗锯齿 borderPaint.setColor(Color.WHITE); //添加边框 /* @param cx要绘制的的圆的圆心的x坐标 @param cy要绘制的圆的圆心的y坐标 @param radius要绘制的线圈半径 @param paint用于绘制圆圈的油漆*/ canvas.drawCircle(canvas.getWidth()/2, canvas.getWidth()/2, newBitmapWH/2, borderPaint); bitmap.recycle();//释放没用的bitmap return newBitmap; }//使用上述方法 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.image3); int height = bitmap.getHeight();//图片的高 int width = bitmap.getWidth();//图片的宽 mTextView.setText("height:"+height+"width:"+width); Bitmap bitmap1 = createRectBitmap(bitmap); RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(),bitmap1); roundedBitmapDrawable.setGravity(Gravity.CENTER);//居中 roundedBitmapDrawable.setCircular(true);//设置为圆形 im01.setImageDrawable(roundedBitmapDrawable);

其他

/**     * 按宽/高缩放图片到指定大小并进行裁剪得到中间部分图片     *     * @param bitmap 源bitmap     * @param w 缩放后指定的宽度     * @param h 缩放后指定的高度     * @return 缩放后的中间部分图片     */    public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scaleWidht, scaleHeight, x, y; Bitmap newbmp; Matrix matrix = new Matrix(); if (width > height) {
scaleWidht = ((float) h / height); scaleHeight = ((float) h / height); x = (width - w * height / h) / 2;//获取bitmap源文件中x做表需要偏移的像数大小 y = 0; } else if (width < height) {
scaleWidht = ((float) w / width); scaleHeight = ((float) w / width); x = 0; y = (height - h * width / w) / 2;//获取bitmap源文件中y做表需要偏移的像数大小 } else {
scaleWidht = ((float) w / width); scaleHeight = ((float) w / width); x = 0; y = 0; } matrix.postScale(scaleWidht, scaleHeight); try {
newbmp = Bitmap.createBitmap(bitmap, (int) x, (int) y, (int) (width - x), (int) (height - y), matrix, true);//createBitmap()方法中定义的参数x+width要小于或等于bitmap.getWidth(),y+height要小于或等于bitmap.getHeight() } catch (Exception e) {
e.printStackTrace(); return null; } return newbmp; }

参考链接:

转载地址:http://vhrii.baihongyu.com/

你可能感兴趣的文章
opencv310安装
查看>>
C++ 调用json
查看>>
nano中设置脚本开机自启动
查看>>
动态库调动态库
查看>>
c++ 操作文件
查看>>
[数据库]mysql必知必会要点
查看>>
[操作系统]进程向内存映射的方式
查看>>
[单片机]51单片机存储器结构
查看>>
[操作系统]锁的实现机制
查看>>
[系统分析]面向对象思考方式
查看>>
[系统分析]UML建模
查看>>
[JAVA]无ide手动编译java文件
查看>>
[信息安全]密码学基础(一)
查看>>
[信息安全]密码学基础(二)
查看>>
[JAVA]码农翻身要点记录
查看>>
VS2015 学习笔记(一):新建C/C++项目、程序调试以及部分头文件缺失及其他小问题的解决办法
查看>>
After Effects(AE) 基本操作(一)
查看>>
FFmpeg学习笔记(一):FFmpeg在win 7 下的安装与使用
查看>>
FFmpeg学习笔记(二):FFmpeg指令学习
查看>>
Direct3D(D3D)简介
查看>>