Android圆形头像图Circle ImageView

桃扇骨 2023-10-16 21:26 129阅读 0赞

《Android圆形头像图Circle ImageView》

需要处理的原始图(pic):

Center

使用CircleImageView处理后的图(作为头像):

Center 1

现在很多的应用都有设置头像的功能,如QQ、微信、微博等。头像有标准的四方形,也有圆形(如QQ)。现在结合他人的代码加以修改,给出一个以原始图形中心为原点,修剪图片为头像的工具类,此类

可以直接在布局文件中加载使用,比如:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <zhangphil.circle.CircleImageView
  6. android:id="@+id/civ"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:src="@drawable/pic" />
  10. </RelativeLayout>

CircleImageView.java的完整源代码:

  1. package zhangphil.circle;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapShader;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Matrix;
  9. import android.graphics.Paint;
  10. import android.graphics.Paint.Align;
  11. import android.graphics.Rect;
  12. import android.graphics.RectF;
  13. import android.graphics.Shader;
  14. import android.graphics.SweepGradient;
  15. import android.graphics.drawable.BitmapDrawable;
  16. import android.graphics.drawable.ColorDrawable;
  17. import android.graphics.drawable.Drawable;
  18. import android.net.Uri;
  19. import android.text.TextPaint;
  20. import android.util.AttributeSet;
  21. import android.util.FloatMath;
  22. import android.widget.ImageView;
  23. /**
  24. * @author Phil
  25. *
  26. */
  27. public class CircleImageView extends ImageView {
  28. private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
  29. private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
  30. private static final int COLORDRAWABLE_DIMENSION = 2;
  31. // 圆形边框的厚度默认值。
  32. // 如果是0,则没有天蓝色渐变的边框。
  33. private static final int DEFAULT_BORDER_WIDTH = 20;
  34. private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
  35. private final RectF mDrawableRect = new RectF();
  36. private final RectF mBorderRect = new RectF();
  37. private final Matrix mShaderMatrix = new Matrix();
  38. private final Paint mBitmapPaint = new Paint();
  39. private final Paint mBorderPaint = new Paint();
  40. private int mBorderColor = DEFAULT_BORDER_COLOR;
  41. private int mBorderWidth = DEFAULT_BORDER_WIDTH;
  42. private Bitmap mBitmap;
  43. private BitmapShader mBitmapShader;
  44. private int mBitmapWidth;
  45. private int mBitmapHeight;
  46. private float mDrawableRadius;
  47. private float mBorderRadius;
  48. private boolean mReady;
  49. private boolean mSetupPending;
  50. private final Paint mFlagBackgroundPaint = new Paint();
  51. private final TextPaint mFlagTextPaint = new TextPaint();
  52. private String mFlagText;
  53. private boolean mShowFlag = false;
  54. private Rect mFlagTextBounds = new Rect();
  55. Shader mSweepGradient = null;
  56. public CircleImageView(Context context) {
  57. super(context);
  58. init();
  59. }
  60. public CircleImageView(Context context, AttributeSet attrs) {
  61. this(context, attrs, 0);
  62. }
  63. public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
  64. super(context, attrs, defStyle);
  65. // TypedArray a = context.obtainStyledAttributes(attrs,
  66. // R.styleable.CircleImageView, defStyle, 0);
  67. //
  68. // mBorderWidth =
  69. // a.getDimensionPixelSize(R.styleable.CircleImageView_border_width,
  70. // DEFAULT_BORDER_WIDTH);
  71. // mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
  72. // DEFAULT_BORDER_COLOR);
  73. //
  74. // a.recycle();
  75. init();
  76. }
  77. private void init() {
  78. super.setScaleType(SCALE_TYPE);
  79. mReady = true;
  80. if (mSetupPending) {
  81. setup();
  82. mSetupPending = false;
  83. }
  84. }
  85. @Override
  86. public ScaleType getScaleType() {
  87. return SCALE_TYPE;
  88. }
  89. @Override
  90. public void setScaleType(ScaleType scaleType) {
  91. if (scaleType != SCALE_TYPE) {
  92. throw new IllegalArgumentException(String.format(
  93. "ScaleType %s not supported.", scaleType));
  94. }
  95. }
  96. @Override
  97. public void setAdjustViewBounds(boolean adjustViewBounds) {
  98. if (adjustViewBounds) {
  99. throw new IllegalArgumentException(
  100. "adjustViewBounds not supported.");
  101. }
  102. }
  103. @Override
  104. protected void onDraw(Canvas canvas) {
  105. if (getDrawable() == null) {
  106. return;
  107. }
  108. canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
  109. mBitmapPaint);
  110. if (mBorderWidth != 0) {
  111. canvas.save();
  112. canvas.rotate(20, getWidth() / 2, getHeight() / 2);
  113. canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
  114. mBorderPaint);
  115. canvas.restore();
  116. }
  117. if (mShowFlag && mFlagText != null) {
  118. canvas.drawArc(mBorderRect, 40, 100, false, mFlagBackgroundPaint);
  119. mFlagTextPaint.getTextBounds(mFlagText, 0, mFlagText.length(),
  120. mFlagTextBounds);
  121. canvas.drawText(mFlagText, getWidth() / 2,
  122. (3 + FloatMath.cos((float) (Math.PI * 5 / 18)))
  123. * getHeight() / 4 + mFlagTextBounds.height() / 3,
  124. mFlagTextPaint);
  125. }
  126. }
  127. @Override
  128. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  129. super.onSizeChanged(w, h, oldw, oldh);
  130. setup();
  131. }
  132. public int getBorderColor() {
  133. return mBorderColor;
  134. }
  135. public void setBorderColor(int borderColor) {
  136. if (borderColor == mBorderColor) {
  137. return;
  138. }
  139. mBorderColor = borderColor;
  140. mBorderPaint.setColor(mBorderColor);
  141. invalidate();
  142. }
  143. public int getBorderWidth() {
  144. return mBorderWidth;
  145. }
  146. /**
  147. * @param borderWidth
  148. * 圆形的边框厚度。
  149. */
  150. public void setBorderWidth(int borderWidth) {
  151. if (borderWidth == mBorderWidth) {
  152. return;
  153. }
  154. mBorderWidth = borderWidth;
  155. setup();
  156. }
  157. @Override
  158. public void setImageBitmap(Bitmap bm) {
  159. super.setImageBitmap(bm);
  160. mBitmap = bm;
  161. setup();
  162. }
  163. @Override
  164. public void setImageDrawable(Drawable drawable) {
  165. super.setImageDrawable(drawable);
  166. mBitmap = getBitmapFromDrawable(drawable);
  167. setup();
  168. }
  169. @Override
  170. public void setImageResource(int resId) {
  171. super.setImageResource(resId);
  172. mBitmap = getBitmapFromDrawable(getDrawable());
  173. setup();
  174. }
  175. @Override
  176. public void setImageURI(Uri uri) {
  177. super.setImageURI(uri);
  178. mBitmap = getBitmapFromDrawable(getDrawable());
  179. setup();
  180. }
  181. private Bitmap getBitmapFromDrawable(Drawable drawable) {
  182. if (drawable == null) {
  183. return null;
  184. }
  185. if (drawable instanceof BitmapDrawable) {
  186. return ((BitmapDrawable) drawable).getBitmap();
  187. }
  188. try {
  189. Bitmap bitmap;
  190. if (drawable instanceof ColorDrawable) {
  191. bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
  192. COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
  193. } else {
  194. bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
  195. drawable.getIntrinsicHeight(), BITMAP_CONFIG);
  196. }
  197. Canvas canvas = new Canvas(bitmap);
  198. drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
  199. drawable.draw(canvas);
  200. return bitmap;
  201. } catch (OutOfMemoryError e) {
  202. return null;
  203. }
  204. }
  205. private void setup() {
  206. if (!mReady) {
  207. mSetupPending = true;
  208. return;
  209. }
  210. if (mBitmap == null) {
  211. return;
  212. }
  213. mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
  214. Shader.TileMode.CLAMP);
  215. mBitmapPaint.setAntiAlias(true);
  216. mBitmapPaint.setShader(mBitmapShader);
  217. mBorderPaint.setStyle(Paint.Style.STROKE);
  218. mBorderPaint.setAntiAlias(true);
  219. mBorderPaint.setColor(mBorderColor);
  220. mBorderPaint.setStrokeWidth(mBorderWidth);
  221. mBitmapHeight = mBitmap.getHeight();
  222. mBitmapWidth = mBitmap.getWidth();
  223. mBorderRect.set(0, 0, getWidth(), getHeight());
  224. mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
  225. (mBorderRect.width() - mBorderWidth) / 2);
  226. mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width()
  227. - mBorderWidth, mBorderRect.height() - mBorderWidth);
  228. mDrawableRadius = Math.min(mDrawableRect.height() / 2,
  229. mDrawableRect.width() / 2);
  230. mFlagBackgroundPaint.setColor(Color.BLACK & 0x66FFFFFF);
  231. mFlagBackgroundPaint.setFlags(TextPaint.ANTI_ALIAS_FLAG);
  232. mFlagTextPaint.setFlags(TextPaint.ANTI_ALIAS_FLAG);
  233. mFlagTextPaint.setTextAlign(Align.CENTER);
  234. mFlagTextPaint.setColor(Color.WHITE);
  235. mFlagTextPaint
  236. .setTextSize(getResources().getDisplayMetrics().density * 18);
  237. mSweepGradient = new SweepGradient(getWidth() / 2, getHeight() / 2,
  238. new int[] { Color.rgb(255, 255, 255), Color.rgb(1, 209, 255) },
  239. null);
  240. mBorderPaint.setShader(mSweepGradient);
  241. updateShaderMatrix();
  242. invalidate();
  243. }
  244. private void updateShaderMatrix() {
  245. float scale;
  246. float dx = 0;
  247. float dy = 0;
  248. mShaderMatrix.set(null);
  249. if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width()
  250. * mBitmapHeight) {
  251. scale = mDrawableRect.height() / (float) mBitmapHeight;
  252. dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
  253. } else {
  254. scale = mDrawableRect.width() / (float) mBitmapWidth;
  255. dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
  256. }
  257. mShaderMatrix.setScale(scale, scale);
  258. mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
  259. (int) (dy + 0.5f) + mBorderWidth);
  260. mBitmapShader.setLocalMatrix(mShaderMatrix);
  261. }
  262. public void setShowFlag(boolean show) {
  263. mShowFlag = show;
  264. invalidate();
  265. }
  266. public void setFlagText(String text) {
  267. mFlagText = text;
  268. invalidate();
  269. }
  270. }



发表评论

表情:
评论列表 (有 0 条评论,129人围观)

还没有评论,来说两句吧...

相关阅读

    相关 圆形头像处理

    很多上传头像是会用到圆形的头像,今天写了一个小方法,可以把图片处理成圆形的,感觉有用的直接拿去用: 不多说直接上代码,希望大家多多支持 //把图片处理成圆形

    相关 Android圆形头像实现

    ![这里写图片描述][SouthEast] 如图所示,实现一个QQ圆形头像,话不多说,直接上代码,继承ImageView类,重写里面的方法: package com