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自定义图片集合,希望大家喜欢。