Android自定义图片集合
本文主要包括以下内容:
- 使用Xfermode设置圆角图片
- 使用BitmapShader设置圆角图片
- 滑动旋转缩放的bimp图片
- 图片颜色处理(滑动)
- 图片+文字
其中1,2是两种不同方式处理图片圆角的情况。3,是通过Matrix进行图片缩放,旋转等。4,是通过Matrix操作图片的处理,包括去饱和,四角黑影,中心突出等。5,图片加文字组合显示。
如果暂时感觉这些看不懂:
先看看这两篇:
Android自定义控件深入学习Android生成随机验证码
详解Android自定义控件属性TypedArray以及attrs
1、使用Xfermode设置圆角图片
主要代码
packagecom.example.customimage.view; importcom.example.customimage.R; importandroid.content.Context; importandroid.content.res.TypedArray; importandroid.graphics.Bitmap; importandroid.graphics.Bitmap.Config; importandroid.graphics.BitmapFactory; importandroid.graphics.Canvas; importandroid.graphics.Paint; importandroid.graphics.PorterDuff; importandroid.graphics.PorterDuffXfermode; importandroid.graphics.RectF; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.util.TypedValue; importandroid.view.View; /** *自定义View,实现圆角,圆形等效果 */ publicclassXfermodeImageViewextendsView { //类型 privateinttype; privatestaticfinalintTYPE_CIRCLE=0;//圆形 privatestaticfinalintTYPE_RECT=1;//矩形圆角 //原始图片 privateBitmapmSrc; //矩形圆角的幅度 privateintmRadius; //控件的宽度 privateintmWidth; //控件的高度 privateintmHeight; publicXfermodeImageView(Contextcontext,AttributeSetattrs) { this(context,attrs,0); } publicXfermodeImageView(Contextcontext) { this(context,null); } /** *初始化一些自定义的参数 * *@paramcontext *@paramattrs *@paramdefStyle */ publicXfermodeImageView(Contextcontext,AttributeSetattrs,intdefStyle) { super(context,attrs,defStyle); TypedArraya=context.getTheme().obtainStyledAttributes(attrs, R.styleable.XfermodeImageView,defStyle,0); intn=a.getIndexCount(); for(inti=0;i<n;i++) { intattr=a.getIndex(i); switch(attr) { //原始图片,在布局里面获取 caseR.styleable.XfermodeImageView_src: mSrc=BitmapFactory.decodeResource(getResources(), a.getResourceId(attr,0)); break; //类型属性选择 caseR.styleable.XfermodeImageView_type: //自定义类型属性,0是圆形,1是矩形圆角 type=a.getInt(attr,0);//默认为Circle break; //矩形圆角幅度的获取,默认是10dp caseR.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 protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { //设置宽度 intspecMode=MeasureSpec.getMode(widthMeasureSpec); intspecSize=MeasureSpec.getSize(widthMeasureSpec); //match_parent或者设置的精确值获取 //MeasureSpec.EXACTLY if(specMode==MeasureSpec.EXACTLY) { mWidth=specSize; } else { //由图片决定的宽 //getPaddingLeft(),getPaddingRight()这两个值是控件属性的向内偏移的距离值,所以的一起计算 //区别于layout_marginLeft,两个控件的左间距值设置 intdesireByImg=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 { intdesire=getPaddingTop()+getPaddingBottom() +mSrc.getHeight(); //wrap_content if(specMode==MeasureSpec.AT_MOST) { mHeight=Math.min(desire,specSize); }else mHeight=desire; } //计算好的宽度以及高度是值,设置进去 setMeasuredDimension(mWidth,mHeight); } /** *绘制image控件 */ @Override protectedvoidonDraw(Canvascanvas) { switch(type) { //如果是TYPE_CIRCLE绘制圆形 caseTYPE_CIRCLE: //圆形宽度和高度应该一致的,所以也要比较一下大小,取小的值 intmin=Math.min(mWidth,mHeight); //圆形宽度和高度如果不一致,按小的值进行压缩 mSrc=Bitmap.createScaledBitmap(mSrc,min,min,false); //绘制圆形 canvas.drawBitmap(createCircleImage(mSrc,min),0,0,null); break; caseTYPE_RECT: canvas.drawBitmap(createRoundConerImage(mSrc),0,0,null); break; } } /** *根据原图和变长绘制圆形图片 * *@paramsource *@parammin *@return */ privateBitmapcreateCircleImage(Bitmapsource,intmin) { finalPaintpaint=newPaint(); //防止边缘的抗锯齿 paint.setAntiAlias(true); Bitmaptarget=Bitmap.createBitmap(min,min,Config.ARGB_8888); //产生一个同样大小的画布 Canvascanvas=newCanvas(target); //首先绘制圆形,除以2就是半径了 //最主要设置第三个参数为min/2,圆角幅度那么大就是圆形了 canvas.drawCircle(min/2,min/2,min/2,paint); //使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示 paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //绘制图片 canvas.drawBitmap(source,0,0,paint); returntarget; } /** *根据原图添加圆角 * *@paramsource *@return */ privateBitmapcreateRoundConerImage(Bitmapsource) { finalPaintpaint=newPaint(); paint.setAntiAlias(true); Bitmaptarget=Bitmap.createBitmap(mWidth,mHeight,Config.ARGB_8888); Canvascanvas=newCanvas(target); //绘制矩形 RectFrect=newRectF(0,0,source.getWidth(),source.getHeight()); //设置圆角幅度 canvas.drawRoundRect(rect,mRadius,mRadius,paint); //使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示 paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(source,0,0,paint); returntarget; } }
2、使用BitmapShader设置圆角图片
packagecom.example.customimage.view; importcom.example.customimage.R; importandroid.content.Context; importandroid.content.res.TypedArray; importandroid.graphics.Bitmap; importandroid.graphics.BitmapShader; importandroid.graphics.Canvas; importandroid.graphics.Matrix; importandroid.graphics.Paint; importandroid.graphics.RectF; importandroid.graphics.Shader.TileMode; importandroid.graphics.drawable.BitmapDrawable; importandroid.graphics.drawable.Drawable; importandroid.os.Bundle; importandroid.os.Parcelable; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.util.TypedValue; importandroid.widget.ImageView; /** * */ publicclassBitmapShaderImageViewextendsImageView { //图片的类型,圆形or圆角 privateinttype; publicstaticfinalintTYPE_CIRCLE=0; publicstaticfinalintTYPE_RECT=1; //圆角大小的默认值 privatestaticfinalintBODER_RADIUS_DEFAULT=10; //圆角的大小 privateintmBorderRadius; //绘图的Paint privatePaintmBitmapPaint; //圆角的半径 privateintmRadius; //3x3矩阵,主要用于缩小放大 privateMatrixmMatrix; //渲染图像,使用图像为绘制图形着色 privateBitmapShadermBitmapShader; //view的宽度 privateintmWidth; //矩形 privateRectFmRoundRect; publicBitmapShaderImageView(Contextcontext) { this(context,null); } publicBitmapShaderImageView(Contextcontext,AttributeSetattrs) { super(context,attrs); mMatrix=newMatrix(); mBitmapPaint=newPaint(); mBitmapPaint.setAntiAlias(true); TypedArraya=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 protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { super.onMeasure(widthMeasureSpec,heightMeasureSpec); //如果类型是圆形,则强制改变view的宽高一致,以小值为准 if(type==TYPE_CIRCLE) { mWidth=Math.min(getMeasuredWidth(),getMeasuredHeight()); //圆形的半径 mRadius=mWidth/2; setMeasuredDimension(mWidth,mWidth); } } //初始化BitmapShader,获取到图片资源 //等待画布的准备好,然后在画布上加上Paint就是了 //就是说图片的载体是Paint privatevoidsetUpShader() { Drawabledrawable=getDrawable(); if(drawable==null) { return; } Bitmapbmp=drawableToBitamp(drawable); //将bmp作为着色器,就是在指定区域内绘制bmp //TileMode.CLAMP拉伸 mBitmapShader=newBitmapShader(bmp,TileMode.CLAMP,TileMode.CLAMP); floatscale=1.0f; if(type==TYPE_CIRCLE) { //拿到bitmap宽或高的小值 intbSize=Math.min(bmp.getWidth(),bmp.getHeight()); scale=mWidth*1.0f/bSize; }elseif(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 protectedvoidonDraw(Canvascanvas) { if(getDrawable()==null) { return; } setUpShader(); if(type==TYPE_RECT) { //绘制矩形 canvas.drawRoundRect(mRoundRect,mBorderRadius,mBorderRadius, mBitmapPaint); }else { //绘制圆形 canvas.drawCircle(mRadius,mRadius,mRadius,mBitmapPaint); } } @Override protectedvoidonSizeChanged(intw,inth,intoldw,intoldh) { super.onSizeChanged(w,h,oldw,oldh); //圆角图片的范围 if(type==TYPE_RECT) mRoundRect=newRectF(0,0,w,h); } //drawable转bitmap privateBitmapdrawableToBitamp(Drawabledrawable) { //从控件的src获取背景,也是drawable文件获取 if(drawableinstanceofBitmapDrawable) { BitmapDrawablebd=(BitmapDrawable)drawable; returnbd.getBitmap(); } //如果没有绘图一个,只不过是空白的图片 intw=drawable.getIntrinsicWidth(); inth=drawable.getIntrinsicHeight(); Bitmapbitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888); Canvascanvas=newCanvas(bitmap); drawable.setBounds(0,0,w,h); drawable.draw(canvas); returnbitmap; } privatestaticfinalStringSTATE_INSTANCE="state_instance"; privatestaticfinalStringSTATE_TYPE="state_type"; privatestaticfinalStringSTATE_BORDER_RADIUS="state_border_radius"; //屏幕旋转后,取出保存的值 @Override protectedParcelableonSaveInstanceState() { Bundlebundle=newBundle(); bundle.putParcelable(STATE_INSTANCE,super.onSaveInstanceState()); bundle.putInt(STATE_TYPE,type); bundle.putInt(STATE_BORDER_RADIUS,mBorderRadius); returnbundle; } //屏幕旋转,变量的保存,因为外面设置值,如果不保存,一旋转就变成个xml里面设置的值 @Override protectedvoidonRestoreInstanceState(Parcelablestate) { if(stateinstanceofBundle) { Bundlebundle=(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); } } //设置矩形圆角幅度后,重新绘制控件 publicvoidsetBorderRadius(intborderRadius) { intpxVal=dp2px(borderRadius); if(this.mBorderRadius!=pxVal) { this.mBorderRadius=pxVal; invalidate(); } } //设置是圆形还是矩形圆角 publicvoidsetType(inttype) { if(this.type!=type) { this.type=type; if(this.type!=TYPE_RECT&&this.type!=TYPE_CIRCLE) { this.type=TYPE_CIRCLE; } requestLayout(); } } //dp转px publicintdp2px(intdpVal) { return(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,getResources().getDisplayMetrics()); } }
3、滑动旋转缩放的bimp图片
packagecom.example.customimage.view; importandroid.content.Context; importandroid.graphics.Bitmap; importandroid.graphics.Canvas; importandroid.graphics.Matrix; importandroid.graphics.Paint; importandroid.graphics.PaintFlagsDrawFilter; importandroid.graphics.PointF; importandroid.graphics.drawable.BitmapDrawable; importandroid.graphics.drawable.Drawable; importandroid.util.AttributeSet; importandroid.view.MotionEvent; importandroid.widget.ImageView; publicclassMatrixImageViewextendsImageView{ privatestaticfinalintMODE_NONE=0x00123;//默认的触摸模式 privatestaticfinalintMODE_DRAG=0x00321;//拖拽模式 privatestaticfinalintMODE_ZOOM=0x00132;//缩放or旋转模式 privateintmode;//当前的触摸模式 privatefloatpreMove=1F;//上一次手指移动的距离 privatefloatsaveRotate=0F;//保存了的角度值 privatefloatrotate=0F;//旋转的角度 privatefloat[]preEventCoor;//上一次各触摸点的坐标集合 privatePointFstartPointF,midPointF;//起点、中点对象 privateMatrixcurrentMatrix,savedMatrix;//当前和保存了的Matrix对象 //原始图片 privateBitmapmSrc; //控件的宽度 privateintmWidth; //控件的高度 privateintmHeight; privatePaintFlagsDrawFiltermDrawFilter; publicMatrixImageView(Contextcontext,AttributeSetattrs){ super(context,attrs); //初始化 init(); } /** *初始化 */ privatevoidinit(){ //实例化对象 currentMatrix=newMatrix(); savedMatrix=newMatrix(); startPointF=newPointF(); midPointF=newPointF(); mDrawFilter=newPaintFlagsDrawFilter(0,Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG); //模式初始化 mode=MODE_NONE; Drawabledrawable=getDrawable(); mSrc=drawableToBitamp(drawable); } /** *计算控件的高度和宽度 */ @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { //设置宽度 intspecMode=MeasureSpec.getMode(widthMeasureSpec); intspecSize=MeasureSpec.getSize(widthMeasureSpec); //match_parent或者设置的精确值获取 //MeasureSpec.EXACTLY if(specMode==MeasureSpec.EXACTLY) { mWidth=specSize; } else { //由图片决定的宽 //getPaddingLeft(),getPaddingRight()这两个值是控件属性的向内偏移的距离值,所以的一起计算 //区别于layout_marginLeft,两个控件的左间距值设置 intdesireByImg=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 { intdesire=getPaddingTop()+getPaddingBottom() +mSrc.getHeight(); //wrap_content if(specMode==MeasureSpec.AT_MOST) { mHeight=Math.min(desire,specSize); }else mHeight=desire; } //计算好的宽度以及高度是值,设置进去 setMeasuredDimension(mWidth,mHeight); } //drawable转bitmap privateBitmapdrawableToBitamp(Drawabledrawable) { //从控件的src获取背景,也是drawable文件获取 if(drawableinstanceofBitmapDrawable) { BitmapDrawablebd=(BitmapDrawable)drawable; returnbd.getBitmap(); } //如果没有绘图一个,只不过是空白的图片 intw=drawable.getIntrinsicWidth(); inth=drawable.getIntrinsicHeight(); Bitmapbitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888); Canvascanvas=newCanvas(bitmap); drawable.setBounds(0,0,w,h); drawable.draw(canvas); returnbitmap; } finalPaintpaint=newPaint(); @Override protectedvoidonDraw(Canvascanvas){ //消除锯齿,图片旋转后的锯齿消除不成功,实在不行图片边缘加一些白色像素点 canvas.setDrawFilter(mDrawFilter); //画经过Matrix变化后的图 canvas.drawBitmap(mSrc,currentMatrix,null); } @Override publicbooleanonTouchEvent(MotionEventevent){ switch(event.getAction()&MotionEvent.ACTION_MASK){ caseMotionEvent.ACTION_DOWN://单点接触屏幕时 savedMatrix.set(currentMatrix); startPointF.set(event.getX(),event.getY()); //单点触摸是移动模式 mode=MODE_DRAG; preEventCoor=null; break; caseMotionEvent.ACTION_POINTER_DOWN://第二个点接触屏幕时 preMove=calSpacing(event); if(preMove>10F){ savedMatrix.set(currentMatrix); //计算两个触摸点的中点坐标 calMidPoint(midPointF,event); //两点是旋转或者缩放模式 mode=MODE_ZOOM; } preEventCoor=newfloat[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; caseMotionEvent.ACTION_UP://单点离开屏幕时 caseMotionEvent.ACTION_POINTER_UP://第二个点离开屏幕时 mode=MODE_NONE; preEventCoor=null; break; caseMotionEvent.ACTION_MOVE://触摸点移动时 /* *单点触控拖拽平移 */ if(mode==MODE_DRAG){ currentMatrix.set(savedMatrix); floatdx=event.getX()-startPointF.x; floatdy=event.getY()-startPointF.y; currentMatrix.postTranslate(dx,dy); } /* *两点触控拖放旋转 */ elseif(mode==MODE_ZOOM&&event.getPointerCount()==2){ floatcurrentMove=calSpacing(event); currentMatrix.set(savedMatrix); /* *指尖移动距离大于10F缩放 */ if(currentMove>10F){ floatscale=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); returntrue; } floatr; /** *计算两个触摸点间的距离 */ privatefloatcalSpacing(MotionEventevent){ floatx=event.getX(0)-event.getX(1); floaty=event.getY(0)-event.getY(1); return(float)Math.sqrt(x*x+y*y); } /** *计算两个触摸点的中点坐标 */ privatevoidcalMidPoint(PointFpoint,MotionEventevent){ floatx=event.getX(0)+event.getX(1); floaty=event.getY(0)+event.getY(1); point.set(x/2,y/2); } /** *计算旋转角度 * *@param事件对象 *@return角度值 */ privatefloatcalRotation(MotionEventevent){ doubledeltaX=(event.getX(0)-event.getX(1)); doubledeltaY=(event.getY(0)-event.getY(1)); doubleradius=Math.atan2(deltaY,deltaX); return(float)Math.toDegrees(radius); } }
4、图片颜色处理(滑动)
packagecom.example.customimage.view; importcom.example.customimage.R; importandroid.content.Context; importandroid.content.res.TypedArray; importandroid.graphics.Bitmap; importandroid.graphics.BitmapFactory; importandroid.graphics.Canvas; importandroid.graphics.Color; importandroid.graphics.ColorMatrixColorFilter; importandroid.graphics.Matrix; importandroid.graphics.Paint; importandroid.graphics.PorterDuff.Mode; importandroid.graphics.PorterDuffXfermode; importandroid.graphics.RadialGradient; importandroid.graphics.Shader.TileMode; importandroid.util.AttributeSet; importandroid.view.View; publicclassDreamEffectViewextendsView{ privatePaintmBitmapPaint,mShaderPaint;//位图画笔和Shader图形的画笔 privatePorterDuffXfermodemXfermode;//图形混合模式 privateintx,y;//位图起点坐标 //控件的宽度 privateintmWidth; //控件的高度 privateintmHeight; //原始图片 privateBitmapmSrc; //生成暗角的图片 privateBitmapdarkCornerBitmap; publicfinalstaticintBITMAP_NULL=0;//原图 privatefinalstaticintBITMAP_DEAST=1;//去饱和 privatefinalstaticintBITMAP_CENTER=2;//中心突出 privatefinalstaticintBITMAP_DARKCORNER=3;//四角黑暗 privateintmnSelectMode=0; publicDreamEffectView(Contextcontext,AttributeSetattrs) { this(context,attrs,0); } publicDreamEffectView(Contextcontext) { this(context,null); } publicDreamEffectView(Contextcontext,AttributeSetattrs,intdefStyle){ super(context,attrs,defStyle); TypedArraya=context.getTheme().obtainStyledAttributes(attrs, R.styleable.DreamEffectView,defStyle,0); intn=a.getIndexCount(); for(inti=0;i<n;i++) { intattr=a.getIndex(i); switch(attr) { //原始图片,在布局里面获取 caseR.styleable.DreamEffectView_src: mSrc=BitmapFactory.decodeResource(getResources(), a.getResourceId(attr,0)); break; caseR.styleable.DreamEffectView_mode: mnSelectMode=a.getInt(attr,0); break; } } a.recycle(); //实例化混合模式 mXfermode=newPorterDuffXfermode(Mode.SCREEN); //初始化画笔 initPaint(); } /** *计算控件的高度和宽度 */ @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { //设置宽度 intspecMode=MeasureSpec.getMode(widthMeasureSpec); intspecSize=MeasureSpec.getSize(widthMeasureSpec); if(specMode==MeasureSpec.EXACTLY) { mWidth=specSize; } else { intdesireByImg=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 { intdesire=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); } /** *初始化画笔 */ privatevoidinitPaint(){ //实例化画笔 mBitmapPaint=newPaint(Paint.ANTI_ALIAS_FLAG); //实例化Shader图形的画笔 mShaderPaint=newPaint(); switch(mnSelectMode){ caseBITMAP_NULL: break; caseBITMAP_DEAST: //去饱和、提亮、色相矫正 mBitmapPaint.setColorFilter(newColorMatrixColorFilter( newfloat[]{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; caseBITMAP_CENTER: //去饱和、提亮、色相矫正 mBitmapPaint.setColorFilter(newColorMatrixColorFilter( newfloat[]{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(newRadialGradient(mWidth/2,mWidth/2,mSrc.getHeight()*7/8,Color.TRANSPARENT, Color.BLACK,TileMode.CLAMP)); break; caseBITMAP_DARKCORNER: //去饱和、提亮、色相矫正 mBitmapPaint.setColorFilter(newColorMatrixColorFilter( newfloat[]{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 Canvascanvas=newCanvas(darkCornerBitmap); //计算径向渐变半径 floatradiu=canvas.getHeight()*(2F/3F); //实例化径向渐变 RadialGradientradialGradient=newRadialGradient(canvas.getWidth()/2F,canvas.getHeight()/2F,radiu,newint[]{0,0,0xAA000000},newfloat[]{0F,0.7F,1.0F},TileMode.CLAMP); //实例化一个矩阵 Matrixmatrix=newMatrix(); //设置矩阵的缩放 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 protectedvoidonDraw(Canvascanvas){ canvas.drawColor(Color.BLACK); //新建图层 intsc=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){ caseBITMAP_NULL: break; caseBITMAP_DEAST: break; caseBITMAP_CENTER: //绘制一个跟图片大小一样的矩形 canvas.drawRect(x,y,x+mSrc.getWidth(),y+mSrc.getHeight(),mShaderPaint); break; caseBITMAP_DARKCORNER: //绘制我们画好的径向渐变图 canvas.drawBitmap(darkCornerBitmap,x,y,null); break; default: break; } } }
1)、实现去饱和、提亮、色相矫正效果的部分代码
mBitmapPaint.setColorFilter(newColorMatrixColorFilter( newfloat[]{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(newRadialGradient(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 Canvascanvas=newCanvas(darkCornerBitmap); //计算径向渐变半径 floatradiu=canvas.getHeight()*(2F/3F); //实例化径向渐变 RadialGradientradialGradient=newRadialGradient(canvas.getWidth()/2F,canvas.getHeight()/2F,radiu,newint[]{0,0,0xAA000000},newfloat[]{0F,0.7F,1.0F},TileMode.CLAMP); //实例化一个矩阵 Matrixmatrix=newMatrix(); //设置矩阵的缩放 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、图片+文字
packagecom.example.customimage.view; importcom.example.customimage.R; importandroid.content.Context; importandroid.content.res.TypedArray; importandroid.graphics.Bitmap; importandroid.graphics.BitmapFactory; importandroid.graphics.Canvas; importandroid.graphics.Color; importandroid.graphics.Paint; importandroid.graphics.PorterDuff; importandroid.graphics.PorterDuffXfermode; importandroid.graphics.RectF; importandroid.graphics.Bitmap.Config; importandroid.graphics.Paint.Style; importandroid.graphics.Rect; importandroid.text.TextPaint; importandroid.text.TextUtils; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.util.TypedValue; importandroid.view.View; publicclassImageViewTextextendsView{ //类型 privateinttype; privatestaticfinalintTYPE_CIRCLE=0;//圆形 privatestaticfinalintTYPE_RECT=1;//矩形圆角 //原始图片 privateBitmapmImage; //控件的宽度 privateintmWidth; //控件的高度 privateintmHeight; //矩形圆角的幅度 privateintmRadius; //图片下面的文字 privateStringmTitle; privateintmTextColor; privateintmTextSize; privateRectrect; privatePaintmPaint; privateRectmTextBound; publicImageViewText(Contextcontext,AttributeSetattrs) { this(context,attrs,0); } publicImageViewText(Contextcontext) { this(context,null); } /** *初始化所特有自定义类型 * *@paramcontext *@paramattrs *@paramdefStyle */ publicImageViewText(Contextcontext,AttributeSetattrs,intdefStyle) { super(context,attrs,defStyle); TypedArraya=context.getTheme().obtainStyledAttributes(attrs,R.styleable.ImageViewText,defStyle,0); intn=a.getIndexCount(); for(inti=0;i<n;i++) { intattr=a.getIndex(i); switch(attr) { //获取图片 caseR.styleable.ImageViewText_image: mImage=BitmapFactory.decodeResource(getResources(),a.getResourceId(attr,0)); break; //获取圆形还是方形 caseR.styleable.ImageViewText_type: type=a.getInt(attr,0); break; //获取文字 caseR.styleable.ImageViewText_titleText: mTitle=a.getString(attr); break; //获取文字的图片 caseR.styleable.ImageViewText_titleTextColor: mTextColor=a.getColor(attr,Color.BLACK); break; //获取文字的大小 caseR.styleable.ImageViewText_titleTextSize: mTextSize=a.getDimensionPixelSize(attr,(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16,getResources().getDisplayMetrics())); break; //矩形圆角幅度的获取,默认是10dp caseR.styleable.ImageViewText_borderRadius: mRadius=a.getDimensionPixelSize(attr,(int)TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP,10f, getResources().getDisplayMetrics())); break; } } a.recycle(); rect=newRect(); mPaint=newPaint(); mTextBound=newRect(); mPaint.setTextSize(mTextSize); //计算了描绘字体需要的范围 mPaint.getTextBounds(mTitle,0,mTitle.length(),mTextBound); } //测量控件的大小 @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { //设置宽度 intspecMode=MeasureSpec.getMode(widthMeasureSpec); intspecSize=MeasureSpec.getSize(widthMeasureSpec); //match_parent,accurate大小 if(specMode==MeasureSpec.EXACTLY) { mWidth=specSize; }else { //由图片决定的宽 intdesireByImg=getPaddingLeft()+getPaddingRight()+mImage.getWidth(); //由字体决定的宽 intdesireByTitle=getPaddingLeft()+getPaddingRight()+mTextBound.width(); //wrap_content大小 if(specMode==MeasureSpec.AT_MOST) { //取小的值 intdesire=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 protectedvoidonDraw(Canvascanvas) { //边框 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) { TextPaintpaint=newTextPaint(mPaint); Stringmsg=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绘制圆形 caseTYPE_CIRCLE: //圆形宽度和高度应该一致的,所以也要比较一下大小,取小的值 intmin=Math.min(mWidth,mHeight); //圆形宽度和高度如果不一致,按小的值进行压缩 mImage=Bitmap.createScaledBitmap(mImage,min,min,false); //绘制圆形 canvas.drawBitmap(createCircleImage(mImage,min),null,rect,null); break; caseTYPE_RECT: canvas.drawBitmap(createRoundConerImage(mImage),null,rect,null); break; } } /** *根据原图和变长绘制圆形图片 * *@paramsource *@parammin *@return */ privateBitmapcreateCircleImage(Bitmapsource,intmin) { finalPaintpaint=newPaint(); //防止边缘的抗锯齿 paint.setAntiAlias(true); Bitmaptarget=Bitmap.createBitmap(min,min,Config.ARGB_8888); //产生一个同样大小的画布 Canvascanvas=newCanvas(target); //首先绘制圆形,除以2就是半径了 //最主要设置第三个参数为min/2,圆角幅度那么大就是圆形了 canvas.drawCircle(min/2,min/2,min/2,paint); //使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示 paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //绘制图片 canvas.drawBitmap(source,0,0,paint); returntarget; } /** *根据原图添加圆角 * *@paramsource *@return */ privateBitmapcreateRoundConerImage(Bitmapsource) { finalPaintpaint=newPaint(); paint.setAntiAlias(true); Bitmaptarget=Bitmap.createBitmap(mWidth,mHeight,Config.ARGB_8888); Canvascanvas=newCanvas(target); //绘制矩形 RectFrect=newRectF(0,0,source.getWidth(),source.getHeight()); //设置圆角幅度 canvas.drawRoundRect(rect,mRadius,mRadius,paint); //使用SRC_IN,参考上面的说明---上下层都显示。下层居上显示 paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(source,0,0,paint); returntarget; } }
是不是很全的Android自定义图片集合,希望大家喜欢。