CircleImageView,a fast circular ImageView perfect for profile images.

主要的类CircleImageView:

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

自定义的属性(不然CircleImageView会报错):res/values/attrs.xml

  1. ?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="CircleImageView">
  4. <attr name="border_width" format="dimension" />
  5. <attr name="border_color" format="color" />
  6. </declare-styleable>
  7. </resources>

使用时的布局文件(注意xmlns:app="http://schemas.android.com/apk/res-auto"):

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical" >
  7. <RelativeLayout
  8. android:layout_width="match_parent"
  9. android:layout_height="0dp"
  10. android:layout_weight="1"
  11. android:padding="@dimen/base_padding"
  12. android:background="@color/light">
  13.  
  14. <de.hdodenhof.circleimageview.CircleImageView
  15. android:layout_width="160dp"
  16. android:layout_height="160dp"
  17. android:layout_centerInParent="true"
  18. android:src="@drawable/demo"
  19. app:border_width="2dp"
  20. app:border_color="@color/dark" />
  21.  
  22. </RelativeLayout>
  23.  
  24. <RelativeLayout
  25. android:layout_width="match_parent"
  26. android:layout_height="0dp"
  27. android:layout_weight="1"
  28. android:padding="@dimen/base_padding"
  29. android:background="@color/dark">
  30.  
  31. <de.hdodenhof.circleimageview.CircleImageView
  32. android:layout_width="160dp"
  33. android:layout_height="160dp"
  34. android:layout_centerInParent="true"
  35. android:src="@drawable/lena"
  36. app:border_width="2dp"
  37. app:border_color="@color/light" />
  38.  
  39. </RelativeLayout>
  40.  
  41. </LinearLayout>

效果图:

Android开发(二)——自定义圆形控件的使用CircleImageView的更多相关文章

  1. Android开发之自定义组合控件

    自定义组合控件的步骤1.自定义一个View,继承ViewGroup,比如RelativeLayout2.编写组合控件的布局文件,在自定义的view中加载(使用View.inflate())3.自定义属 ...

  2. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  3. 自定义圆形控件RoundImageView并认识一下attr.xml

    今天我们来讲一下有关自定义控件的问题,今天讲的这篇是从布局自定义开始的,难度不大,一看就明白,估计有的同学或者开发者看了说,这种方式多此一举,但是小编我不这么认为,多一种解决方式,就多一种举一反三的学 ...

  4. 自定义圆形控件RoundImageView并认识一下attr

    昨天我们学习了自定义带图片和文字的ImageTextButton,非常简单,我承诺给大家要讲一下用自定义属性的方式学习真正的实现自定义控件,在布局文件中使用属性的方式就需要用到attr.xml这个文件 ...

  5. 自定义圆形控件 RoundImageView

    1.自定义圆形控件 RoundImageView package com.ronye.CustomView; import android.content.Context; import androi ...

  6. CircleImageView自定义圆形控件的使用

    1.自定义圆形控件github地址: https://github.com/hdodenhof/CircleImageView 主要的类: package de.hdodenhof.circleima ...

  7. Android开发中目前流行控件和知识点总结

    Android开发中目前流行控件和知识点总结   1.SlidingMenu 滑动菜单 应用案例:Facebook . Path 2.0 .人人.网易新闻 下载地址: https://github.c ...

  8. Android开发工程师文集-相关控件的讲解,五大布局

    前言 大家好,给大家带来Android开发工程师文集-相关控件的讲解,五大布局的概述,希望你们喜欢 TextView控件 TextView控件有哪些属性: android:id->控件的id a ...

  9. Android自定义控件之自定义组合控件(三)

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

随机推荐

  1. C语言学习笔记 (006) - 二维数组传参的三种表现形式

    # include <stdio.h> # include <stdlib.h> # define M # define N int getdate(int (*sp)[M]) ...

  2. 树莓派进阶之路 (015) - 树莓派使用DS18B20模块测量温度

    参考:http://shumeipai.nxez.com/2013/10/03/raspberry-pi-temperature-sensor-monitors.html 第一步,允许单总线接口 su ...

  3. 题目要求:将a,b两个数的值进行交换,并且不使用任何的中间变量。

    a = a+b; b = a-b; a = a-b;

  4. jenkins执行shell命令提示找不到命令解决办法

    用jenkins执行shell脚本,执行一条命令: #唤醒休眠手机 adb shell input keyevent 提示: [adb] $ /bin/sh -xe /Users/xxxxx/tool ...

  5. haproxy 日志配置

    haproxy日志配置 haproxy在默认情况不会记录日志,除了在haproxy.conf中的global段指定日志的输出外,还需要配置系统日志的配置文件.下面以centos6.4为例,haprox ...

  6. ELK logstash邮件报警

    这个方法有一个问题就是我这边不能给我们公司的邮箱发邮件.还有就是我们有两个邮箱一个是腾讯企业邮箱,还有一个就是我们的集团邮箱 使用下面的这个方法是不能给我们的集团邮箱发邮件的.第二个问题就是这个方法给 ...

  7. [转]在 javascript 按键事件中,按键值的对照表

    转自:http://www.phpweblog.net/kiyone/archive/2007/04/19/1138.html 话说谁知道怎么能精简下word生成的html代码....好大啊... 字 ...

  8. Android 源码解析:单例模式-通过容器实现单例模式-懒加载方式

    本文分析了 Android 系统服务通过容器实现单例,确保系统服务的全局唯一. 开发过 Android 的用户肯定都用过这句代码,主要作用是把布局文件 XML 加载到系统中,转换为 Android 的 ...

  9. C#-微信公众平台接口-上传临时素材

    最烦做微信公众平台的东西..文档说得不清不楚,又没示例代码,只能自己 慢慢搜索,弄了一晚上,基本弄出来了,把本地的图片上传到微信的临时素材那里,返回媒体ID,用于其他操作,代码如下 :(自己导入相应的 ...

  10. 2.1 Apache Axis2 快速学习手册之 POJO 构建Web Service

    1. 准备:创建一个Maven Web App 项目 这里让我们使用Maven 模板创建一个Web App 项目 1. New------> Maven Project 2. 使用默认配置,点击 ...