之前使用过,现在做下记录
-
自定义圆形控件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);
}
}