Android自定义图片集合
程序员文章站
2024-02-16 10:28:46
本文主要包括以下内容:
使用xfermode设置圆角图片
使用bitmapshader设置圆角图片
滑动旋转缩放的bimp图片
图片颜色处理...
本文主要包括以下内容:
- 使用xfermode设置圆角图片
- 使用bitmapshader设置圆角图片
- 滑动旋转缩放的bimp图片
- 图片颜色处理(滑动)
-
图片 + 文字
其中1,2是两种不同方式处理图片圆角的情况。3,是通过matrix进行图片缩放,旋转等。4,是通过matrix操作图片的处理,包括去饱和,四角黑影,中心突出等。5,图片加文字组合显示。
如果暂时感觉这些看不懂:
先看看这两篇:
android自定义控件深入学习 android生成随机验证码
详解android自定义控件属性typedarray以及attrs
1、使用xfermode设置圆角图片
主要代码
package com.example.customimage.view; import com.example.customimage.r; import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmap.config; import android.graphics.bitmapfactory; import android.graphics.canvas; import android.graphics.paint; import android.graphics.porterduff; import android.graphics.porterduffxfermode; import android.graphics.rectf; import android.util.attributeset; import android.util.log; import android.util.typedvalue; import android.view.view; /** * 自定义view,实现圆角,圆形等效果 */ public class xfermodeimageview extends view { //类型 private int type; private static final int type_circle = 0; //圆形 private static final int type_rect = 1; //矩形圆角 //原始图片 private bitmap msrc; //矩形圆角的幅度 private int mradius; //控件的宽度 private int mwidth; // 控件的高度 private int mheight; public xfermodeimageview(context context, attributeset attrs) { this(context, attrs, 0); } public xfermodeimageview(context context) { this(context, null); } /** * 初始化一些自定义的参数 * * @param context * @param attrs * @param defstyle */ public xfermodeimageview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.xfermodeimageview, defstyle, 0); int n = a.getindexcount(); for (int i = 0; i < n; i++) { int attr = a.getindex(i); switch (attr) { //原始图片,在布局里面获取 case r.styleable.xfermodeimageview_src: msrc = bitmapfactory.decoderesource(getresources(), a.getresourceid(attr, 0)); break; //类型属性选择 case r.styleable.xfermodeimageview_type: //自定义类型属性,0是圆形,1是矩形圆角 type = a.getint(attr, 0);// 默认为circle break; //矩形圆角幅度的获取,默认是10dp case r.styleable.xfermodeimageview_borderradius: mradius = a.getdimensionpixelsize(attr, (int) typedvalue .applydimension(typedvalue.complex_unit_dip, 10f, getresources().getdisplaymetrics())); log.i("show", string.valueof(mradius)); break; } } a.recycle(); } /** * 计算控件的高度和宽度 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // 设置宽度 int specmode = measurespec.getmode(widthmeasurespec); int specsize = measurespec.getsize(widthmeasurespec); //match_parent或者设置的精确值获取 //measurespec.exactly if (specmode == measurespec.exactly) { mwidth = specsize; } else { // 由图片决定的宽 //getpaddingleft(),getpaddingright()这两个值是控件属性的向内偏移的距离值,所以的一起计算 //区别于layout_marginleft,两个控件的左间距值设置 int desirebyimg = getpaddingleft() + getpaddingright() + msrc.getwidth(); // wrap_content if (specmode == measurespec.at_most) { //所以最小的值,宽度的话是左右内偏移距离之和 mwidth = math.min(desirebyimg, specsize); } else mwidth = desirebyimg; } // 设置高度,部分解释同上 specmode = measurespec.getmode(heightmeasurespec); specsize = measurespec.getsize(heightmeasurespec); //match_parent或者设置的精确值获取 //measurespec.exactly if (specmode == measurespec.exactly) { mheight = specsize; } else { int desire = getpaddingtop() + getpaddingbottom() + msrc.getheight(); // wrap_content if (specmode == measurespec.at_most) { mheight = math.min(desire, specsize); } else mheight = desire; } //计算好的宽度以及高度是值,设置进去 setmeasureddimension(mwidth, mheight); } /** * 绘制image控件 */ @override protected void ondraw(canvas canvas) { switch (type) { // 如果是type_circle绘制圆形 case type_circle: //圆形宽度和高度应该一致的,所以也要比较一下大小,取小的值 int min = math.min(mwidth, mheight); // 圆形宽度和高度如果不一致,按小的值进行压缩 msrc = bitmap.createscaledbitmap(msrc, min, min, false); //绘制圆形 canvas.drawbitmap(createcircleimage(msrc, min), 0, 0, null); break; case type_rect: canvas.drawbitmap(createroundconerimage(msrc), 0, 0, null); break; } } /** * 根据原图和变长绘制圆形图片 * * @param source * @param min * @return */ private bitmap createcircleimage(bitmap source, int min) { final paint paint = new paint(); //防止边缘的抗锯齿 paint.setantialias(true); bitmap target = bitmap.createbitmap(min, min, config.argb_8888); // 产生一个同样大小的画布 canvas canvas = new canvas(target); // 首先绘制圆形,除以2就是半径了 //最主要设置第三个参数为min/2,圆角幅度那么大就是圆形了 canvas.drawcircle(min / 2, min / 2, min/2, paint); // 使用src_in,参考上面的说明---上下层都显示。下层居上显示 paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in)); // 绘制图片 canvas.drawbitmap(source, 0, 0, paint); return target; } /** * 根据原图添加圆角 * * @param source * @return */ private bitmap createroundconerimage(bitmap source) { final paint paint = new paint(); paint.setantialias(true); bitmap target = bitmap.createbitmap(mwidth, mheight, config.argb_8888); canvas canvas = new canvas(target); //绘制矩形 rectf rect = new rectf(0, 0, source.getwidth(), source.getheight()); //设置圆角幅度 canvas.drawroundrect(rect, mradius, mradius, paint); // 使用src_in,参考上面的说明---上下层都显示。下层居上显示 paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in)); canvas.drawbitmap(source, 0, 0, paint); return target; } }
2、使用bitmapshader设置圆角图片
package com.example.customimage.view; import com.example.customimage.r; import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmapshader; import android.graphics.canvas; import android.graphics.matrix; import android.graphics.paint; import android.graphics.rectf; import android.graphics.shader.tilemode; import android.graphics.drawable.bitmapdrawable; import android.graphics.drawable.drawable; import android.os.bundle; import android.os.parcelable; import android.util.attributeset; import android.util.log; import android.util.typedvalue; import android.widget.imageview; /** * */ public class bitmapshaderimageview extends imageview { // 图片的类型,圆形or圆角 private int type; public static final int type_circle = 0; public static final int type_rect = 1; //圆角大小的默认值 private static final int boder_radius_default = 10; //圆角的大小 private int mborderradius; // 绘图的paint private paint mbitmappaint; //圆角的半径 private int mradius; // 3x3 矩阵,主要用于缩小放大 private matrix mmatrix; // 渲染图像,使用图像为绘制图形着色 private bitmapshader mbitmapshader; // view的宽度 private int mwidth; //矩形 private rectf mroundrect; public bitmapshaderimageview(context context) { this(context, null); } public bitmapshaderimageview(context context, attributeset attrs) { super(context, attrs); mmatrix = new matrix(); mbitmappaint = new paint(); mbitmappaint.setantialias(true); typedarray a = context.obtainstyledattributes(attrs, r.styleable.bitmapshaderimageview); //矩形圆角幅度的获取,默认是10dp mborderradius = a.getdimensionpixelsize( r.styleable.bitmapshaderimageview_borderradius, (int) typedvalue .applydimension(typedvalue.complex_unit_dip, boder_radius_default, getresources() .getdisplaymetrics())); //自定义类型属性,0是圆形,1是矩形圆角 type = a.getint(r.styleable.bitmapshaderimageview_type, type_circle); a.recycle(); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); // 如果类型是圆形,则强制改变view的宽高一致,以小值为准 if (type == type_circle) { mwidth = math.min(getmeasuredwidth(), getmeasuredheight()); //圆形的半径 mradius = mwidth / 2; setmeasureddimension(mwidth, mwidth); } } // 初始化bitmapshader,获取到图片资源 // 等待画布的准备好,然后在画布上加上paint就是了 //就是说图片的载体是paint private void setupshader() { drawable drawable = getdrawable(); if (drawable == null) { return; } bitmap bmp = drawabletobitamp(drawable); // 将bmp作为着色器,就是在指定区域内绘制bmp //tilemode.clamp 拉伸 mbitmapshader = new bitmapshader(bmp, tilemode.clamp, tilemode.clamp); float scale = 1.0f; if (type == type_circle) { // 拿到bitmap宽或高的小值 int bsize = math.min(bmp.getwidth(), bmp.getheight()); scale = mwidth * 1.0f / bsize; } else if (type == type_rect) { if (!(bmp.getwidth() == getwidth() && bmp.getheight() == getheight())) { // 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值; scale = math.max(getwidth() * 1.0f / bmp.getwidth(), getheight() * 1.0f / bmp.getheight()); } } // shader的变换矩阵,我们这里主要用于放大或者缩小 // scale * scale 的矩阵 mmatrix.setscale(scale, scale); // 设置变换矩阵 mbitmapshader.setlocalmatrix(mmatrix); // 设置shader mbitmappaint.setshader(mbitmapshader); } @override protected void ondraw(canvas canvas) { if (getdrawable() == null) { return; } setupshader(); if (type == type_rect) { //绘制矩形 canvas.drawroundrect(mroundrect, mborderradius, mborderradius, mbitmappaint); } else { //绘制圆形 canvas.drawcircle(mradius, mradius, mradius, mbitmappaint); } } @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(w, h, oldw, oldh); // 圆角图片的范围 if (type == type_rect) mroundrect = new rectf(0, 0, w, h); } //drawable转bitmap private bitmap drawabletobitamp(drawable drawable) { //从控件的src获取背景,也是drawable文件获取 if (drawable instanceof bitmapdrawable) { bitmapdrawable bd = (bitmapdrawable) drawable; return bd.getbitmap(); } //如果没有绘图一个,只不过是空白的图片 int w = drawable.getintrinsicwidth(); int h = drawable.getintrinsicheight(); bitmap bitmap = bitmap.createbitmap(w, h, bitmap.config.argb_8888); canvas canvas = new canvas(bitmap); drawable.setbounds(0, 0, w, h); drawable.draw(canvas); return bitmap; } private static final string state_instance = "state_instance"; private static final string state_type = "state_type"; private static final string state_border_radius = "state_border_radius"; //屏幕旋转后,取出保存的值 @override protected parcelable onsaveinstancestate() { bundle bundle = new bundle(); bundle.putparcelable(state_instance, super.onsaveinstancestate()); bundle.putint(state_type, type); bundle.putint(state_border_radius, mborderradius); return bundle; } //屏幕旋转,变量的保存,因为外面设置值,如果不保存,一旋转就变成个xml里面设置的值 @override protected void onrestoreinstancestate(parcelable state) { if (state instanceof bundle) { bundle bundle = (bundle) state; super.onrestoreinstancestate(((bundle) state) .getparcelable(state_instance)); this.type = bundle.getint(state_type); this.mborderradius = bundle.getint(state_border_radius); } else { super.onrestoreinstancestate(state); } } //设置矩形圆角幅度后,重新绘制控件 public void setborderradius(int borderradius) { int pxval = dp2px(borderradius); if (this.mborderradius != pxval) { this.mborderradius = pxval; invalidate(); } } //设置是圆形还是矩形圆角 public void settype(int type) { if (this.type != type) { this.type = type; if (this.type != type_rect && this.type != type_circle) { this.type = type_circle; } requestlayout(); } } //dp转px public int dp2px(int dpval) { return (int) typedvalue.applydimension(typedvalue.complex_unit_dip, dpval, getresources().getdisplaymetrics()); } }
3、滑动旋转缩放的bimp图片
package com.example.customimage.view; import android.content.context; import android.graphics.bitmap; import android.graphics.canvas; import android.graphics.matrix; import android.graphics.paint; import android.graphics.paintflagsdrawfilter; import android.graphics.pointf; import android.graphics.drawable.bitmapdrawable; import android.graphics.drawable.drawable; import android.util.attributeset; import android.view.motionevent; import android.widget.imageview; public class matriximageview extends imageview { private static final int mode_none = 0x00123;// 默认的触摸模式 private static final int mode_drag = 0x00321;// 拖拽模式 private static final int mode_zoom = 0x00132;// 缩放or旋转模式 private int mode;// 当前的触摸模式 private float premove = 1f;// 上一次手指移动的距离 private float saverotate = 0f;// 保存了的角度值 private float rotate = 0f;// 旋转的角度 private float[] preeventcoor;// 上一次各触摸点的坐标集合 private pointf startpointf, midpointf;// 起点、中点对象 private matrix currentmatrix, savedmatrix;// 当前和保存了的matrix对象 //原始图片 private bitmap msrc; //控件的宽度 private int mwidth; // 控件的高度 private int mheight; private paintflagsdrawfilter mdrawfilter; public matriximageview(context context, attributeset attrs) { super(context, attrs); // 初始化 init(); } /** * 初始化 */ private void init() { // 实例化对象 currentmatrix = new matrix(); savedmatrix = new matrix(); startpointf = new pointf(); midpointf = new pointf(); mdrawfilter = new paintflagsdrawfilter(0, paint.anti_alias_flag|paint.filter_bitmap_flag); // 模式初始化 mode = mode_none; drawable drawable = getdrawable(); msrc = drawabletobitamp(drawable); } /** * 计算控件的高度和宽度 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // 设置宽度 int specmode = measurespec.getmode(widthmeasurespec); int specsize = measurespec.getsize(widthmeasurespec); //match_parent或者设置的精确值获取 //measurespec.exactly if (specmode == measurespec.exactly) { mwidth = specsize; } else { // 由图片决定的宽 //getpaddingleft(),getpaddingright()这两个值是控件属性的向内偏移的距离值,所以的一起计算 //区别于layout_marginleft,两个控件的左间距值设置 int desirebyimg = getpaddingleft() + getpaddingright() + msrc.getwidth(); // wrap_content if (specmode == measurespec.at_most) { //所以最小的值,宽度的话是左右内偏移距离之和 mwidth = math.min(desirebyimg, specsize); } else mwidth = desirebyimg; } // 设置高度,部分解释同上 specmode = measurespec.getmode(heightmeasurespec); specsize = measurespec.getsize(heightmeasurespec); //match_parent或者设置的精确值获取 //measurespec.exactly if (specmode == measurespec.exactly) { mheight = specsize; } else { int desire = getpaddingtop() + getpaddingbottom() + msrc.getheight(); // wrap_content if (specmode == measurespec.at_most) { mheight = math.min(desire, specsize); } else mheight = desire; } //计算好的宽度以及高度是值,设置进去 setmeasureddimension(mwidth, mheight); } //drawable转bitmap private bitmap drawabletobitamp(drawable drawable) { //从控件的src获取背景,也是drawable文件获取 if (drawable instanceof bitmapdrawable) { bitmapdrawable bd = (bitmapdrawable) drawable; return bd.getbitmap(); } //如果没有绘图一个,只不过是空白的图片 int w = drawable.getintrinsicwidth(); int h = drawable.getintrinsicheight(); bitmap bitmap = bitmap.createbitmap(w, h, bitmap.config.argb_8888); canvas canvas = new canvas(bitmap); drawable.setbounds(0, 0, w, h); drawable.draw(canvas); return bitmap; } final paint paint = new paint(); @override protected void ondraw(canvas canvas) { //消除锯齿, 图片旋转后的锯齿消除不成功,实在不行图片边缘加一些白色像素点 canvas.setdrawfilter(mdrawfilter); //画经过matrix变化后的图 canvas.drawbitmap(msrc, currentmatrix, null); } @override public boolean ontouchevent(motionevent event) { switch (event.getaction() & motionevent.action_mask) { case motionevent.action_down:// 单点接触屏幕时 savedmatrix.set(currentmatrix); startpointf.set(event.getx(), event.gety()); //单点触摸是移动模式 mode = mode_drag; preeventcoor = null; break; case motionevent.action_pointer_down:// 第二个点接触屏幕时 premove = calspacing(event); if (premove > 10f) { savedmatrix.set(currentmatrix); // 计算两个触摸点的中点坐标 calmidpoint(midpointf, event); //两点是旋转或者缩放模式 mode = mode_zoom; } preeventcoor = new float[4]; preeventcoor[0] = event.getx(0); preeventcoor[1] = event.getx(1); preeventcoor[2] = event.gety(0); preeventcoor[3] = event.gety(1); saverotate = calrotation(event); break; case motionevent.action_up:// 单点离开屏幕时 case motionevent.action_pointer_up:// 第二个点离开屏幕时 mode = mode_none; preeventcoor = null; break; case motionevent.action_move:// 触摸点移动时 /* * 单点触控拖拽平移 */ if (mode == mode_drag) { currentmatrix.set(savedmatrix); float dx = event.getx() - startpointf.x; float dy = event.gety() - startpointf.y; currentmatrix.posttranslate(dx, dy); } /* * 两点触控拖放旋转 */ else if (mode == mode_zoom && event.getpointercount() == 2) { float currentmove = calspacing(event); currentmatrix.set(savedmatrix); /* * 指尖移动距离大于10f缩放 */ if (currentmove > 10f) { float scale = currentmove / premove; currentmatrix.postscale(scale, scale, midpointf.x, midpointf.y); } /* * 保持两点时旋转 */ if (preeventcoor != null) { rotate = calrotation(event); r = rotate - saverotate; currentmatrix.postrotate(r, getmeasuredwidth() / 2, getmeasuredheight() / 2); } } break; } setimagematrix(currentmatrix); return true; } float r; /** * 计算两个触摸点间的距离 */ private float calspacing(motionevent event) { float x = event.getx(0) - event.getx(1); float y = event.gety(0) - event.gety(1); return (float) math.sqrt(x * x + y * y); } /** * 计算两个触摸点的中点坐标 */ private void calmidpoint(pointf point, motionevent event) { float x = event.getx(0) + event.getx(1); float y = event.gety(0) + event.gety(1); point.set(x / 2, y / 2); } /** * 计算旋转角度 * * @param 事件对象 * @return 角度值 */ private float calrotation(motionevent event) { double deltax = (event.getx(0) - event.getx(1)); double deltay = (event.gety(0) - event.gety(1)); double radius = math.atan2(deltay, deltax); return (float) math.todegrees(radius); } }
4、图片颜色处理(滑动)
package com.example.customimage.view; import com.example.customimage.r; import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.canvas; import android.graphics.color; import android.graphics.colormatrixcolorfilter; import android.graphics.matrix; import android.graphics.paint; import android.graphics.porterduff.mode; import android.graphics.porterduffxfermode; import android.graphics.radialgradient; import android.graphics.shader.tilemode; import android.util.attributeset; import android.view.view; public class dreameffectview extends view { private paint mbitmappaint, mshaderpaint;// 位图画笔和shader图形的画笔 private porterduffxfermode mxfermode;// 图形混合模式 private int x, y;// 位图起点坐标 //控件的宽度 private int mwidth; // 控件的高度 private int mheight; //原始图片 private bitmap msrc; //生成暗角的图片 private bitmap darkcornerbitmap; public final static int bitmap_null = 0; //原图 private final static int bitmap_deast = 1; //去饱和 private final static int bitmap_center = 2; //中心突出 private final static int bitmap_darkcorner = 3; //四角黑暗 private int mnselectmode = 0; public dreameffectview(context context, attributeset attrs) { this(context, attrs, 0); } public dreameffectview(context context) { this(context, null); } public dreameffectview(context context, attributeset attrs, int defstyle) { super(context, attrs,defstyle); typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.dreameffectview, defstyle, 0); int n = a.getindexcount(); for (int i = 0; i < n; i++) { int attr = a.getindex(i); switch (attr) { //原始图片,在布局里面获取 case r.styleable.dreameffectview_src: msrc = bitmapfactory.decoderesource(getresources(), a.getresourceid(attr, 0)); break; case r.styleable.dreameffectview_mode: mnselectmode = a.getint(attr, 0); break; } } a.recycle(); // 实例化混合模式 mxfermode = new porterduffxfermode(mode.screen); // 初始化画笔 initpaint(); } /** * 计算控件的高度和宽度 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // 设置宽度 int specmode = measurespec.getmode(widthmeasurespec); int specsize = measurespec.getsize(widthmeasurespec); if (specmode == measurespec.exactly) { mwidth = specsize; } else { int desirebyimg = getpaddingleft() + getpaddingright() + msrc.getwidth(); // wrap_content if (specmode == measurespec.at_most) { //所以最小的值,宽度的话是左右内偏移距离之和 mwidth = math.min(desirebyimg, specsize); } else mwidth = desirebyimg; } // 设置高度,部分解释同上 specmode = measurespec.getmode(heightmeasurespec); specsize = measurespec.getsize(heightmeasurespec); if (specmode == measurespec.exactly) { mheight = specsize; } else { int desire = getpaddingtop() + getpaddingbottom() + msrc.getheight(); // wrap_content if (specmode == measurespec.at_most) { mheight = math.min(desire, specsize); } else mheight = desire; } x = mwidth / 2 - msrc.getwidth() / 2; y = mheight / 2 - msrc.getheight() / 2; //计算好的宽度以及高度是值,设置进去 setmeasureddimension(mwidth, mheight); } /** * 初始化画笔 */ private void initpaint() { // 实例化画笔 mbitmappaint = new paint(paint.anti_alias_flag); // 实例化shader图形的画笔 mshaderpaint = new paint(); switch (mnselectmode) { case bitmap_null: break; case bitmap_deast: // 去饱和、提亮、色相矫正 mbitmappaint.setcolorfilter(new colormatrixcolorfilter( new float[] { 0.8587f, 0.2940f, -0.0927f, 0, 6.79f, 0.0821f, 0.9145f, 0.0634f, 0, 6.79f, 0.2019f, 0.1097f, 0.7483f, 0, 6.79f, 0, 0, 0, 1, 0 })); break; case bitmap_center: // 去饱和、提亮、色相矫正 mbitmappaint.setcolorfilter(new colormatrixcolorfilter( new float[] { 0.8587f, 0.2940f, -0.0927f, 0, 6.79f, 0.0821f, 0.9145f, 0.0634f, 0, 6.79f, 0.2019f, 0.1097f, 0.7483f, 0, 6.79f, 0, 0, 0, 1, 0 })); // 设置径向渐变,渐变中心当然是图片的中心也是屏幕中心,渐变半径我们直接拿图片的高度但是要稍微小一点 // 中心颜色为透明而边缘颜色为黑色 mshaderpaint.setshader(new radialgradient(mwidth / 2, mwidth / 2, msrc.getheight() * 7 / 8, color.transparent, color.black, tilemode.clamp)); break; case bitmap_darkcorner: // 去饱和、提亮、色相矫正 mbitmappaint.setcolorfilter(new colormatrixcolorfilter( new float[] { 0.8587f, 0.2940f, -0.0927f, 0, 6.79f, 0.0821f, 0.9145f, 0.0634f, 0, 6.79f, 0.2019f, 0.1097f, 0.7483f, 0, 6.79f, 0, 0, 0, 1, 0 })); // 根据我们源图的大小生成暗角bitmap darkcornerbitmap = bitmap.createbitmap(msrc.getwidth(), msrc.getheight(), bitmap.config.argb_8888); // 将该暗角bitmap注入canvas canvas canvas = new canvas(darkcornerbitmap); // 计算径向渐变半径 float radiu = canvas.getheight() * (2f / 3f); // 实例化径向渐变 radialgradient radialgradient = new radialgradient(canvas.getwidth() / 2f, canvas.getheight() / 2f, radiu, new int[] { 0, 0, 0xaa000000 }, new float[] { 0f, 0.7f, 1.0f }, tilemode.clamp); // 实例化一个矩阵 matrix matrix = new matrix(); // 设置矩阵的缩放 matrix.setscale(canvas.getwidth() / (radiu * 2f), 1.0f); // 设置矩阵的预平移 matrix.pretranslate(((radiu * 2f) - canvas.getwidth()) / 2f, 0); // 将该矩阵注入径向渐变 radialgradient.setlocalmatrix(matrix); // 设置画笔shader mshaderpaint.setshader(radialgradient); // 绘制矩形 canvas.drawrect(0, 0, canvas.getwidth(), canvas.getheight(), mshaderpaint); break; default: break; } } @override protected void ondraw(canvas canvas) { canvas.drawcolor(color.black); // 新建图层 int sc = canvas.savelayer(x, y, x + msrc.getwidth(), y + msrc.getheight(), null, canvas.all_save_flag); // 绘制混合颜色 canvas.drawcolor(0xcc1c093e); // 设置混合模式 mbitmappaint.setxfermode(mxfermode); // 绘制位图 canvas.drawbitmap(msrc, x, y, mbitmappaint); // 还原混合模式 mbitmappaint.setxfermode(null); // 还原画布 canvas.restoretocount(sc); switch (mnselectmode) { case bitmap_null: break; case bitmap_deast: break; case bitmap_center: // 绘制一个跟图片大小一样的矩形 canvas.drawrect(x, y, x + msrc.getwidth(), y + msrc.getheight(),mshaderpaint); break; case bitmap_darkcorner: // 绘制我们画好的径向渐变图 canvas.drawbitmap(darkcornerbitmap, x, y, null); break; default: break; } } }
1)、实现 去饱和、提亮、色相矫正 效果的部分代码
mbitmappaint.setcolorfilter(new colormatrixcolorfilter( new float[] { 0.8587f, 0.2940f, -0.0927f, 0, 6.79f, 0.0821f, 0.9145f, 0.0634f, 0, 6.79f, 0.2019f, 0.1097f, 0.7483f, 0, 6.79f, 0, 0, 0, 1, 0 }));
2)、实现中心颜色为透明而边缘颜色为黑色效果的部分代码
mshaderpaint.setshader(new radialgradient(mwidth / 2, mwidth / 2, msrc.getheight() * 7 / 8, color.transparent, color.black, tilemode.clamp));
3)、实现四角黑暗效果的部分代码
// 根据我们源图的大小生成暗角bitmap darkcornerbitmap = bitmap.createbitmap(msrc.getwidth(), msrc.getheight(), bitmap.config.argb_8888); // 将该暗角bitmap注入canvas canvas canvas = new canvas(darkcornerbitmap); // 计算径向渐变半径 float radiu = canvas.getheight() * (2f / 3f); // 实例化径向渐变 radialgradient radialgradient = new radialgradient(canvas.getwidth() / 2f, canvas.getheight() / 2f, radiu, new int[] { 0, 0, 0xaa000000 }, new float[] { 0f, 0.7f, 1.0f }, tilemode.clamp); // 实例化一个矩阵 matrix matrix = new matrix(); // 设置矩阵的缩放 matrix.setscale(canvas.getwidth() / (radiu * 2f), 1.0f); // 设置矩阵的预平移 matrix.pretranslate(((radiu * 2f) - canvas.getwidth()) / 2f, 0); // 将该矩阵注入径向渐变 radialgradient.setlocalmatrix(matrix); // 设置画笔shader mshaderpaint.setshader(radialgradient); // 绘制矩形 canvas.drawrect(0, 0, canvas.getwidth(), canvas.getheight(), mshaderpaint);
5、图片 + 文字
package com.example.customimage.view; import com.example.customimage.r; import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.porterduff; import android.graphics.porterduffxfermode; import android.graphics.rectf; import android.graphics.bitmap.config; import android.graphics.paint.style; import android.graphics.rect; import android.text.textpaint; import android.text.textutils; import android.util.attributeset; import android.util.log; import android.util.typedvalue; import android.view.view; public class imageviewtext extends view{ //类型 private int type; private static final int type_circle = 0; //圆形 private static final int type_rect = 1; //矩形圆角 //原始图片 private bitmap mimage; //控件的宽度 private int mwidth; // 控件的高度 private int mheight; //矩形圆角的幅度 private int mradius; //图片下面的文字 private string mtitle; private int mtextcolor; private int mtextsize; private rect rect; private paint mpaint; private rect mtextbound; public imageviewtext(context context, attributeset attrs) { this(context, attrs, 0); } public imageviewtext(context context) { this(context, null); } /** * 初始化所特有自定义类型 * * @param context * @param attrs * @param defstyle */ public imageviewtext(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.imageviewtext, defstyle, 0); int n = a.getindexcount(); for (int i = 0; i < n; i++) { int attr = a.getindex(i); switch (attr) { //获取图片 case r.styleable.imageviewtext_image: mimage = bitmapfactory.decoderesource(getresources(), a.getresourceid(attr, 0)); break; //获取圆形还是方形 case r.styleable.imageviewtext_type: type = a.getint(attr, 0); break; //获取文字 case r.styleable.imageviewtext_titletext: mtitle = a.getstring(attr); break; //获取文字的图片 case r.styleable.imageviewtext_titletextcolor: mtextcolor = a.getcolor(attr, color.black); break; //获取文字的大小 case r.styleable.imageviewtext_titletextsize: mtextsize = a.getdimensionpixelsize(attr, (int) typedvalue.applydimension(typedvalue.complex_unit_sp, 16, getresources().getdisplaymetrics())); break; //矩形圆角幅度的获取,默认是10dp case r.styleable.imageviewtext_borderradius: mradius = a.getdimensionpixelsize(attr, (int) typedvalue .applydimension(typedvalue.complex_unit_dip, 10f, getresources().getdisplaymetrics())); break; } } a.recycle(); rect = new rect(); mpaint = new paint(); mtextbound = new rect(); mpaint.settextsize(mtextsize); // 计算了描绘字体需要的范围 mpaint.gettextbounds(mtitle, 0, mtitle.length(), mtextbound); } //测量控件的大小 @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { //设置宽度 int specmode = measurespec.getmode(widthmeasurespec); int specsize = measurespec.getsize(widthmeasurespec); // match_parent , accurate 大小 if (specmode == measurespec.exactly) { mwidth = specsize; } else { // 由图片决定的宽 int desirebyimg = getpaddingleft() + getpaddingright() + mimage.getwidth(); // 由字体决定的宽 int desirebytitle = getpaddingleft() + getpaddingright() + mtextbound.width(); //wrap_content 大小 if (specmode == measurespec.at_most) { //取小的值 int desire = math.max(desirebyimg, desirebytitle); mwidth = math.min(desire, specsize); } } //设置高度 specmode = measurespec.getmode(heightmeasurespec); // match_parent , accurate 大小 if (specmode == measurespec.exactly) { mheight = specsize; } else { //wrap_content 大小 mheight = getpaddingtop() + getpaddingbottom() + mimage.getheight() + mtextbound.height(); } //测量好的大小设置进去 setmeasureddimension(mwidth, mheight); } @override protected void ondraw(canvas canvas) { // 边框 mpaint.setstrokewidth(4); mpaint.setstyle(paint.style.stroke); mpaint.setcolor(color.cyan); canvas.drawrect(0, 0, getmeasuredwidth(), getmeasuredheight(), mpaint); mpaint.setcolor(mtextcolor); mpaint.setstyle(style.fill); //当前设置的宽度小于字体需要的宽度,将字体改为 //绘制文字 if (mtextbound.width() > mwidth) { textpaint paint = new textpaint(mpaint); string msg = textutils.ellipsize(mtitle, paint, (float) mwidth - getpaddingleft() - getpaddingright(), textutils.truncateat.end).tostring(); canvas.drawtext(msg, getpaddingleft(), mheight - getpaddingbottom(), mpaint); } else { //正常情况,将字体居中 canvas.drawtext(mtitle, mwidth / 2 - mtextbound.width() * 1.0f / 2, mheight - getpaddingbottom(), mpaint); } //计算居中的矩形范围 rect.left = mwidth / 2 - mimage.getwidth() / 2 + getpaddingleft(); rect.right = mwidth / 2 + mimage.getwidth() / 2 + getpaddingright(); rect.top = (mheight - mtextbound.height()) / 2 - mimage.getheight() / 2 + getpaddingtop(); rect.bottom = (mheight - mtextbound.height()) / 2 + mimage.getheight() / 2 + getpaddingbottom(); switch (type) { // 如果是type_circle绘制圆形 case type_circle: //圆形宽度和高度应该一致的,所以也要比较一下大小,取小的值 int min = math.min(mwidth, mheight); // 圆形宽度和高度如果不一致,按小的值进行压缩 mimage = bitmap.createscaledbitmap(mimage, min, min, false); //绘制圆形 canvas.drawbitmap(createcircleimage(mimage, min), null, rect, null); break; case type_rect: canvas.drawbitmap(createroundconerimage(mimage), null, rect, null); break; } } /** * 根据原图和变长绘制圆形图片 * * @param source * @param min * @return */ private bitmap createcircleimage(bitmap source, int min) { final paint paint = new paint(); //防止边缘的抗锯齿 paint.setantialias(true); bitmap target = bitmap.createbitmap(min, min, config.argb_8888); // 产生一个同样大小的画布 canvas canvas = new canvas(target); // 首先绘制圆形,除以2就是半径了 //最主要设置第三个参数为min/2,圆角幅度那么大就是圆形了 canvas.drawcircle(min / 2, min / 2, min/2, paint); // 使用src_in,参考上面的说明---上下层都显示。下层居上显示 paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in)); // 绘制图片 canvas.drawbitmap(source, 0, 0, paint); return target; } /** * 根据原图添加圆角 * * @param source * @return */ private bitmap createroundconerimage(bitmap source) { final paint paint = new paint(); paint.setantialias(true); bitmap target = bitmap.createbitmap(mwidth, mheight, config.argb_8888); canvas canvas = new canvas(target); //绘制矩形 rectf rect = new rectf(0, 0, source.getwidth(), source.getheight()); //设置圆角幅度 canvas.drawroundrect(rect, mradius, mradius, paint); // 使用src_in,参考上面的说明---上下层都显示。下层居上显示 paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in)); canvas.drawbitmap(source, 0, 0, paint); return target; } }
是不是很全的android自定义图片集合,希望大家喜欢。