本文共 9527 字,大约阅读时间需要 31 分钟。
官网上查看Drawable 的实现类,如ShapeDrawable,BitmapDrawable,ClipDrawable,RoundBitmapDrawable,StateListDrawableRoateDrawable。我们今天就是大致介绍一下比较常用的类。Drawable 是一种媒介,它可以把内容绘制到 Canvas 上。
一个创建图形的 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),会出现实心圆形。
- 这里要说下这个 useLevel, 只有在 LevelListDrawable 中才设置 true,这里要设置 false,否则显示不出来。
- 其实 GradientDrawable 或者说是 ShapeDrawable 的绘制原理就是利用 Canvas.drawCircle() ,Canvas.drawRect() 等等方法(Canvas 我将在后面的文章介绍)。
图层列表,就像我们平时把一张照片放在另外一张照片上,最后的照片在最上面。 LayerListDrawable 就是这样设计的。
经典案例: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 = new ColorDrawable(Color.RED);imageView.setBackground(colorDrawable);
其实这个名字应该叫做 圆角图片,它是设置图片四个角的圆形半径。当图片是矩形的时候,就有四个圆角,再特殊一点,如果图片是正方形,正好圆角的半径为正方形边长的一半,那么它就是一个圆。
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/