CircleImageView 圆形图片头像实现

package com.view.drop;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * Copyright 2014 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.
 *
 */
public class CircleImageView extends ImageView {

	private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;

	private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
	private static final int COLORDRAWABLE_DIMENSION = 1;

	private static final int DEFAULT_BORDER_WIDTH = 0;
	private static final int DEFAULT_BORDER_COLOR = Color.BLACK;

	private final RectF mDrawableRect = new RectF();
	private final RectF mBorderRect = new RectF();

	private final Matrix mShaderMatrix = new Matrix();
	private final Paint mBitmapPaint = new Paint();
	private final Paint mBorderPaint = new Paint();

	private int mBorderColor = DEFAULT_BORDER_COLOR;
	private int mBorderWidth = DEFAULT_BORDER_WIDTH;

	private Bitmap mBitmap;
	private BitmapShader mBitmapShader;
	private int mBitmapWidth;
	private int mBitmapHeight;

	private float mDrawableRadius;
	private float mBorderRadius;

	private boolean mReady;
	private boolean mSetupPending;

	public CircleImageView(Context context) {
		super(context);
	}

	public CircleImageView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		super.setScaleType(SCALE_TYPE);

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

		mBorderWidth = a.getDimensionPixelSize(
				R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
		mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
				DEFAULT_BORDER_COLOR);

		a.recycle();

		mReady = true;

		if (mSetupPending) {
			setup();
			mSetupPending = false;
		}
	}

	@Override
	public ScaleType getScaleType() {
		return SCALE_TYPE;
	}

	@Override
	public void setScaleType(ScaleType scaleType) {
		if (scaleType != SCALE_TYPE) {
			throw new IllegalArgumentException(String.format(
					"ScaleType %s not supported.", scaleType));
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		if (getDrawable() == null) {
			return;
		}

		canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
				mBitmapPaint);
		if (mBorderWidth != 0) {
			canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
					mBorderPaint);
		}
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		setup();
	}

	public int getBorderColor() {
		return mBorderColor;
	}

	public void setBorderColor(int borderColor) {
		if (borderColor == mBorderColor) {
			return;
		}

		mBorderColor = borderColor;
		mBorderPaint.setColor(mBorderColor);
		invalidate();
	}

	public int getBorderWidth() {
		return mBorderWidth;
	}

	public void setBorderWidth(int borderWidth) {
		if (borderWidth == mBorderWidth) {
			return;
		}

		mBorderWidth = borderWidth;
		setup();
	}

	@Override
	public void setImageBitmap(Bitmap bm) {
		super.setImageBitmap(bm);
		mBitmap = bm;
		setup();
	}

	@Override
	public void setImageDrawable(Drawable drawable) {
		super.setImageDrawable(drawable);
		mBitmap = getBitmapFromDrawable(drawable);
		setup();
	}

	@Override
	public void setImageResource(int resId) {
		super.setImageResource(resId);
		mBitmap = getBitmapFromDrawable(getDrawable());
		setup();
	}

	private Bitmap getBitmapFromDrawable(Drawable drawable) {
		if (drawable == null) {
			return null;
		}

		if (drawable instanceof BitmapDrawable) {
			return ((BitmapDrawable) drawable).getBitmap();
		}

		try {
			Bitmap bitmap;

			if (drawable instanceof ColorDrawable) {
				bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
						COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
			} else {
				bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
						drawable.getIntrinsicHeight(), BITMAP_CONFIG);
			}

			Canvas canvas = new Canvas(bitmap);
			drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
			drawable.draw(canvas);
			return bitmap;
		} catch (OutOfMemoryError e) {
			return null;
		}
	}

	private void setup() {
		if (!mReady) {
			mSetupPending = true;
			return;
		}

		if (mBitmap == null) {
			return;
		}

		mBitmapShader = new BitmapShader(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);

		mBitmapHeight = mBitmap.getHeight();
		mBitmapWidth = mBitmap.getWidth();

		mBorderRect.set(0, 0, getWidth(), getHeight());
		mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
				(mBorderRect.width() - mBorderWidth) / 2);

		mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width()
				- mBorderWidth, mBorderRect.height() - mBorderWidth);
		mDrawableRadius = Math.min(mDrawableRect.height() / 2,
				mDrawableRect.width() / 2);

		updateShaderMatrix();
		invalidate();
	}

	private void updateShaderMatrix() {
		float scale;
		float dx = 0;
		float dy = 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) + mBorderWidth,
				(int) (dy + 0.5f) + mBorderWidth);

		mBitmapShader.setLocalMatrix(mShaderMatrix);
	}

}

  

时间: 2024-10-10 00:46:28

CircleImageView 圆形图片头像实现的相关文章

Android Glide+CircleImageView实现加载圆形图片列表

需求:要在列表中实现圆形图片的显示,控件可能和加载库会存在冲突 先上代码,至于其中源码,以后有空再分析 MainActivity public class MainActivity extends Activity { ArrayList<String> fileNames = new ArrayList<String>(); // 本地图片路径 ImageAdapter imageAdapter; @Override protected void onCreate(Bundle

Windows Phone 8.1中圆形图片或头像的制作、优化以及Stretch的四个属性值的区别

开篇之前,认识一下Stretch的四个不同的属性值: 现在很多应用的头像或者其他UI设计都偏向于圆形,当然也存在方块形的Metro风格的布局.在Win10手机预览版里的 联系人头像都改成圆形显示了.其实真不知道微软怎么想的,有些自己创造或者发起的东西自己又不坚持了,然后被 苹果安卓的发扬光大,这不是给别人做嫁妆嘛.这样市场怎么起得来,真是恨铁不成钢啊. 算了,废话一大堆,在程序员看来,有需求就必须要实现,也必须有实现的方法.很简单方法如下: 两种方式,前者普遍,后者重在优化. <Grid> &

圆形图片带有边框可以自定义边框颜色

最近需要一个圆形的头像,但是还需要实现带有边框边框具有颜色,于是发现了一个不错的自定义圆形图片circleimageview 废话不多说,先感谢 文章作者:http://blog.csdn.net/nupt123456789/article/details/24886451 源码作者:https://github.com/hdodenhof/CircleImageView 使用方式请参考码源,里面介绍了非常简单也很清楚了 主要就是下边这几句话 Gradle dependencies { ...

Android自定义圆形图片

最近研究了一下圆形图片控件,之前一直是用别人写好的类,自己写一下,发现对canvas理解更深入了. 基本思路: 自定义CircleImageView继承自ImageView,在canvas中新建一个图层,先把要显示的头像绘制在上面,再绘制圆形遮罩,设置画笔模式为:当两个图像重叠时,显示交叉部分下面的图像. 源码如下:(直接拿去用就可以了) package com.lt.DrawDemo; import android.content.Context; import android.graphic

自定义圆形图片

圆形图片相必是项目开发中也是不少用的一个知识点吧. 那么这里学习一下简单的制作圆形图片,主要运用 BitmapShader 类的知识来实现 一.首先,了解一下 BitmapShader 类 BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置 看一下BitmapShader 的构造方法 BitmapShader bitmapShader = new BitmapShader(bitmap,TileMode, TileMode)

Android_AsyncTaskDemo之QQ记步数(画圆形图片知识)

今天学习了AsyncTask Android 的异步机制.我简单的实现我的一个小小案例--qq记步数.然后穿插一个画圆形图片的知识点. 由于所学知识有限,目前我计数,还有排名等等我就简单的利用随机数实现.多有不是之处见谅啊. 我们的xml layout布局文件 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.a

iOS开发Quzrtz2D 十:圆形图片的绘制以及加边框圆形图片的绘制

一:圆形图片的绘制 @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageV; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; /** * UIBezierPath:绘制路径,就是根据路径对图形上下文进行构造 */ //0.加载图片 UIImage *image = [UII

圆形图片2

直接引用 package com.bwie.test; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.P

【WinRT】【译】【加工】在 XAML 中制作圆形图片

原文地址:http://timheuer.com/blog/archive/2015/05/06/making-circular-images-in-xaml-easily.aspx 前阵子似乎一些比较酷的程序开始使用圆形头像来取代之前方形或者圆角边的显示方式了.我(原文作者.下文中如果没特别提到,均指原文作者)在两年前注意到一些 App 开始这样做的时候,做出了一个偏激的发言: 看看吧,程序里会越来越多圆形的头像了,方形的将不会再有了 ——Tim Heuer(@timheuer) 2013 年