Android自定义圆形控件CircleImageView

之前使用过,现在做下记录

  • 自定义圆形控件github地址:

https://github.com/hdodenhof/CircleImageView

  • 使用方式


  • 自定义控件源码

/*

* Copyright 2014 - 2016 Henning Dodenhof

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*    http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

packagede.hdodenhof.circleimageview;

importandroid.content.Context;

importandroid.content.res.TypedArray;

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapShader;

importandroid.graphics.Canvas;

importandroid.graphics.Color;

importandroid.graphics.ColorFilter;

importandroid.graphics.Matrix;

importandroid.graphics.Paint;

importandroid.graphics.RectF;

importandroid.graphics.Shader;

importandroid.graphics.drawable.BitmapDrawable;

importandroid.graphics.drawable.ColorDrawable;

importandroid.graphics.drawable.Drawable;

importandroid.net.Uri;

importandroid.support.annotation.ColorInt;

importandroid.support.annotation.ColorRes;

importandroid.support.annotation.DrawableRes;

importandroid.util.AttributeSet;

importandroid.widget.ImageView;

publicclassCircleImageViewextendsImageView{

privatestaticfinalScaleTypeSCALE_TYPE=ScaleType.CENTER_CROP;

privatestaticfinalBitmap.ConfigBITMAP_CONFIG=Bitmap.Config.ARGB_8888;

privatestaticfinalintCOLORDRAWABLE_DIMENSION=2;

privatestaticfinalintDEFAULT_BORDER_WIDTH=0;

privatestaticfinalintDEFAULT_BORDER_COLOR=Color.BLACK;

privatestaticfinalintDEFAULT_FILL_COLOR=Color.TRANSPARENT;

privatestaticfinalbooleanDEFAULT_BORDER_OVERLAY=false;

privatefinalRectFmDrawableRect=newRectF();

privatefinalRectFmBorderRect=newRectF();

privatefinalMatrixmShaderMatrix=newMatrix();

privatefinalPaintmBitmapPaint=newPaint();

privatefinalPaintmBorderPaint=newPaint();

privatefinalPaintmFillPaint=newPaint();

privateintmBorderColor=DEFAULT_BORDER_COLOR;

privateintmBorderWidth=DEFAULT_BORDER_WIDTH;

privateintmFillColor=DEFAULT_FILL_COLOR;

privateBitmapmBitmap;

privateBitmapShadermBitmapShader;

privateintmBitmapWidth;

privateintmBitmapHeight;

privatefloatmDrawableRadius;

privatefloatmBorderRadius;

privateColorFiltermColorFilter;

privatebooleanmReady;

privatebooleanmSetupPending;

privatebooleanmBorderOverlay;

privatebooleanmDisableCircularTransformation;

publicCircleImageView(Contextcontext) {

super(context);

init();

}

publicCircleImageView(Contextcontext,AttributeSetattrs) {

this(context, attrs,0);

}

publicCircleImageView(Contextcontext,AttributeSetattrs,intdefStyle) {

super(context, attrs, defStyle);

TypedArraya=context.obtainStyledAttributes(attrs,R.styleable.CircleImageView, defStyle,0);

mBorderWidth=a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width,DEFAULT_BORDER_WIDTH);

mBorderColor=a.getColor(R.styleable.CircleImageView_civ_border_color,DEFAULT_BORDER_COLOR);

mBorderOverlay=a.getBoolean(R.styleable.CircleImageView_civ_border_overlay,DEFAULT_BORDER_OVERLAY);

mFillColor=a.getColor(R.styleable.CircleImageView_civ_fill_color,DEFAULT_FILL_COLOR);

a.recycle();

init();

}

privatevoidinit() {

super.setScaleType(SCALE_TYPE);

mReady=true;

if(mSetupPending) {

setup();

mSetupPending=false;

}

}

@Override

publicScaleTypegetScaleType() {

returnSCALE_TYPE;

}

@Override

publicvoidsetScaleType(ScaleTypescaleType) {

if(scaleType!=SCALE_TYPE) {

thrownewIllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));

}

}

@Override

publicvoidsetAdjustViewBounds(booleanadjustViewBounds) {

if(adjustViewBounds) {

thrownewIllegalArgumentException("adjustViewBounds not supported.");

}

}

@Override

protectedvoidonDraw(Canvascanvas) {

if(mDisableCircularTransformation) {

super.onDraw(canvas);

return;

}

if(mBitmap==null) {

return;

}

if(mFillColor!=Color.TRANSPARENT) {

canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);

}

canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);

if(mBorderWidth>0) {

canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);

}

}

@Override

protectedvoidonSizeChanged(intw,inth,intoldw,intoldh) {

super.onSizeChanged(w, h, oldw, oldh);

setup();

}

@Override

publicvoidsetPadding(intleft,inttop,intright,intbottom) {

super.setPadding(left, top, right, bottom);

setup();

}

@Override

publicvoidsetPaddingRelative(intstart,inttop,intend,intbottom) {

super.setPaddingRelative(start, top, end, bottom);

setup();

}

publicintgetBorderColor() {

returnmBorderColor;

}

publicvoidsetBorderColor(@ColorIntintborderColor) {

if(borderColor==mBorderColor) {

return;

}

mBorderColor=borderColor;

mBorderPaint.setColor(mBorderColor);

invalidate();

}

/**

* @deprecated Use {@link #setBorderColor(int)} instead

*/

@Deprecated

publicvoidsetBorderColorResource(@ColorResintborderColorRes) {

setBorderColor(getContext().getResources().getColor(borderColorRes));

}

/**

* Return the color drawn behind the circle-shaped drawable.

*

* @return The color drawn behind the drawable

*

* @deprecated Fill color support is going to be removed in the future

*/

@Deprecated

publicintgetFillColor() {

returnmFillColor;

}

/**

* Set a color to be drawn behind the circle-shaped drawable. Note that

* this has no effect if the drawable is opaque or no drawable is set.

*

* @param fillColor The color to be drawn behind the drawable

*

* @deprecated Fill color support is going to be removed in the future

*/

@Deprecated

publicvoidsetFillColor(@ColorIntintfillColor) {

if(fillColor==mFillColor) {

return;

}

mFillColor=fillColor;

mFillPaint.setColor(fillColor);

invalidate();

}

/**

* Set a color to be drawn behind the circle-shaped drawable. Note that

* this has no effect if the drawable is opaque or no drawable is set.

*

* @param fillColorRes The color resource to be resolved to a color and

*                    drawn behind the drawable

*

* @deprecated Fill color support is going to be removed in the future

*/

@Deprecated

publicvoidsetFillColorResource(@ColorResintfillColorRes) {

setFillColor(getContext().getResources().getColor(fillColorRes));

}

publicintgetBorderWidth() {

returnmBorderWidth;

}

publicvoidsetBorderWidth(intborderWidth) {

if(borderWidth==mBorderWidth) {

return;

}

mBorderWidth=borderWidth;

setup();

}

publicbooleanisBorderOverlay() {

returnmBorderOverlay;

}

publicvoidsetBorderOverlay(booleanborderOverlay) {

if(borderOverlay==mBorderOverlay) {

return;

}

mBorderOverlay=borderOverlay;

setup();

}

publicbooleanisDisableCircularTransformation() {

returnmDisableCircularTransformation;

}

publicvoidsetDisableCircularTransformation(booleandisableCircularTransformation) {

if(mDisableCircularTransformation==disableCircularTransformation) {

return;

}

mDisableCircularTransformation=disableCircularTransformation;

initializeBitmap();

}

@Override

publicvoidsetImageBitmap(Bitmapbm) {

super.setImageBitmap(bm);

initializeBitmap();

}

@Override

publicvoidsetImageDrawable(Drawabledrawable) {

super.setImageDrawable(drawable);

initializeBitmap();

}

@Override

publicvoidsetImageResource(@DrawableResintresId) {

super.setImageResource(resId);

initializeBitmap();

}

@Override

publicvoidsetImageURI(Uriuri) {

super.setImageURI(uri);

initializeBitmap();

}

@Override

publicvoidsetColorFilter(ColorFiltercf) {

if(cf==mColorFilter) {

return;

}

mColorFilter=cf;

applyColorFilter();

invalidate();

}

@Override

publicColorFiltergetColorFilter() {

returnmColorFilter;

}

privatevoidapplyColorFilter() {

if(mBitmapPaint!=null) {

mBitmapPaint.setColorFilter(mColorFilter);

}

}

privateBitmapgetBitmapFromDrawable(Drawabledrawable) {

if(drawable==null) {

returnnull;

}

if(drawableinstanceofBitmapDrawable) {

return((BitmapDrawable) drawable).getBitmap();

}

try{

Bitmapbitmap;

if(drawableinstanceofColorDrawable) {

bitmap=Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,COLORDRAWABLE_DIMENSION,BITMAP_CONFIG);

}else{

bitmap=Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),BITMAP_CONFIG);

}

Canvascanvas=newCanvas(bitmap);

drawable.setBounds(0,0, canvas.getWidth(), canvas.getHeight());

drawable.draw(canvas);

returnbitmap;

}catch(Exceptione) {

e.printStackTrace();

returnnull;

}

}

privatevoidinitializeBitmap() {

if(mDisableCircularTransformation) {

mBitmap=null;

}else{

mBitmap=getBitmapFromDrawable(getDrawable());

}

setup();

}

privatevoidsetup() {

if(!mReady) {

mSetupPending=true;

return;

}

if(getWidth()==0&&getHeight()==0) {

return;

}

if(mBitmap==null) {

invalidate();

return;

}

mBitmapShader=newBitmapShader(mBitmap,Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);

mBitmapPaint.setAntiAlias(true);

mBitmapPaint.setShader(mBitmapShader);

mBorderPaint.setStyle(Paint.Style.STROKE);

mBorderPaint.setAntiAlias(true);

mBorderPaint.setColor(mBorderColor);

mBorderPaint.setStrokeWidth(mBorderWidth);

mFillPaint.setStyle(Paint.Style.FILL);

mFillPaint.setAntiAlias(true);

mFillPaint.setColor(mFillColor);

mBitmapHeight=mBitmap.getHeight();

mBitmapWidth=mBitmap.getWidth();

mBorderRect.set(calculateBounds());

mBorderRadius=Math.min((mBorderRect.height()-mBorderWidth)/2.0f, (mBorderRect.width()-mBorderWidth)/2.0f);

mDrawableRect.set(mBorderRect);

if(!mBorderOverlay&&mBorderWidth>0) {

mDrawableRect.inset(mBorderWidth-1.0f, mBorderWidth-1.0f);

}

mDrawableRadius=Math.min(mDrawableRect.height()/2.0f, mDrawableRect.width()/2.0f);

applyColorFilter();

updateShaderMatrix();

invalidate();

}

privateRectFcalculateBounds() {

intavailableWidth=getWidth()-getPaddingLeft()-getPaddingRight();

intavailableHeight=getHeight()-getPaddingTop()-getPaddingBottom();

intsideLength=Math.min(availableWidth, availableHeight);

floatleft=getPaddingLeft()+(availableWidth-sideLength)/2f;

floattop=getPaddingTop()+(availableHeight-sideLength)/2f;

returnnewRectF(left, top, left+sideLength, top+sideLength);

}

privatevoidupdateShaderMatrix() {

floatscale;

floatdx=0;

floatdy=0;

mShaderMatrix.set(null);

if(mBitmapWidth*mDrawableRect.height()>mDrawableRect.width()*mBitmapHeight) {

scale=mDrawableRect.height()/(float) mBitmapHeight;

dx=(mDrawableRect.width()-mBitmapWidth*scale)*0.5f;

}else{

scale=mDrawableRect.width()/(float) mBitmapWidth;

dy=(mDrawableRect.height()-mBitmapHeight*scale)*0.5f;

}

mShaderMatrix.setScale(scale, scale);

mShaderMatrix.postTranslate((int) (dx+0.5f)+mDrawableRect.left, (int) (dy+0.5f)+mDrawableRect.top);

mBitmapShader.setLocalMatrix(mShaderMatrix);

}

}

你可能感兴趣的:(Android自定义圆形控件CircleImageView)