CircleImageView自定义圆形控件的使用

怼烎@ 2023-07-13 13:38 142阅读 0赞

1.自定义圆形控件github地址:https://github.com/hdodenhof/CircleImageView

  1. package de.hdodenhof.circleimageview;
  2. import edu.njupt.zhb.main.R;
  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.Matrix;
  10. import android.graphics.Paint;
  11. import android.graphics.RectF;
  12. import android.graphics.Shader;
  13. import android.graphics.drawable.BitmapDrawable;
  14. import android.graphics.drawable.ColorDrawable;
  15. import android.graphics.drawable.Drawable;
  16. import android.util.AttributeSet;
  17. import android.widget.ImageView;
  18. public class CircleImageView extends ImageView {
  19. private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
  20. private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
  21. private static final int COLORDRAWABLE_DIMENSION = 1;
  22. private static final int DEFAULT_BORDER_WIDTH = 0;
  23. private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
  24. private final RectF mDrawableRect = new RectF();
  25. private final RectF mBorderRect = new RectF();
  26. private final Matrix mShaderMatrix = new Matrix();
  27. private final Paint mBitmapPaint = new Paint();
  28. private final Paint mBorderPaint = new Paint();
  29. private int mBorderColor = DEFAULT_BORDER_COLOR;
  30. private int mBorderWidth = DEFAULT_BORDER_WIDTH;
  31. private Bitmap mBitmap;
  32. private BitmapShader mBitmapShader;
  33. private int mBitmapWidth;
  34. private int mBitmapHeight;
  35. private float mDrawableRadius;
  36. private float mBorderRadius;
  37. private boolean mReady;
  38. private boolean mSetupPending;
  39. public CircleImageView(Context context) {
  40. super(context);
  41. }
  42. public CircleImageView(Context context, AttributeSet attrs) {
  43. this(context, attrs, 0);
  44. }
  45. public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
  46. super(context, attrs, defStyle);
  47. super.setScaleType(SCALE_TYPE);
  48. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
  49. mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
  50. mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
  51. a.recycle();
  52. mReady = true;
  53. if (mSetupPending) {
  54. setup();
  55. mSetupPending = false;
  56. }
  57. }
  58. @Override
  59. public ScaleType getScaleType() {
  60. return SCALE_TYPE;
  61. }
  62. @Override
  63. public void setScaleType(ScaleType scaleType) {
  64. if (scaleType != SCALE_TYPE) {
  65. throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
  66. }
  67. }
  68. @Override
  69. protected void onDraw(Canvas canvas) {
  70. if (getDrawable() == null) {
  71. return;
  72. }
  73. canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
  74. canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
  75. }
  76. @Override
  77. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  78. super.onSizeChanged(w, h, oldw, oldh);
  79. setup();
  80. }
  81. public int getBorderColor() {
  82. return mBorderColor;
  83. }
  84. public void setBorderColor(int borderColor) {
  85. if (borderColor == mBorderColor) {
  86. return;
  87. }
  88. mBorderColor = borderColor;
  89. mBorderPaint.setColor(mBorderColor);
  90. invalidate();
  91. }
  92. public int getBorderWidth() {
  93. return mBorderWidth;
  94. }
  95. public void setBorderWidth(int borderWidth) {
  96. if (borderWidth == mBorderWidth) {
  97. return;
  98. }
  99. mBorderWidth = borderWidth;
  100. setup();
  101. }
  102. @Override
  103. public void setImageBitmap(Bitmap bm) {
  104. super.setImageBitmap(bm);
  105. mBitmap = bm;
  106. setup();
  107. }
  108. @Override
  109. public void setImageDrawable(Drawable drawable) {
  110. super.setImageDrawable(drawable);
  111. mBitmap = getBitmapFromDrawable(drawable);
  112. setup();
  113. }
  114. @Override
  115. public void setImageResource(int resId) {
  116. super.setImageResource(resId);
  117. mBitmap = getBitmapFromDrawable(getDrawable());
  118. setup();
  119. }
  120. private Bitmap getBitmapFromDrawable(Drawable drawable) {
  121. if (drawable == null) {
  122. return null;
  123. }
  124. if (drawable instanceof BitmapDrawable) {
  125. return ((BitmapDrawable) drawable).getBitmap();
  126. }
  127. try {
  128. Bitmap bitmap;
  129. if (drawable instanceof ColorDrawable) {
  130. bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
  131. } else {
  132. bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
  133. }
  134. Canvas canvas = new Canvas(bitmap);
  135. drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
  136. drawable.draw(canvas);
  137. return bitmap;
  138. } catch (OutOfMemoryError e) {
  139. return null;
  140. }
  141. }
  142. private void setup() {
  143. if (!mReady) {
  144. mSetupPending = true;
  145. return;
  146. }
  147. if (mBitmap == null) {
  148. return;
  149. }
  150. mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  151. mBitmapPaint.setAntiAlias(true);
  152. mBitmapPaint.setShader(mBitmapShader);
  153. mBorderPaint.setStyle(Paint.Style.STROKE);
  154. mBorderPaint.setAntiAlias(true);
  155. mBorderPaint.setColor(mBorderColor);
  156. mBorderPaint.setStrokeWidth(mBorderWidth);
  157. mBitmapHeight = mBitmap.getHeight();
  158. mBitmapWidth = mBitmap.getWidth();
  159. mBorderRect.set(0, 0, getWidth(), getHeight());
  160. mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);
  161. mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);
  162. mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
  163. updateShaderMatrix();
  164. invalidate();
  165. }
  166. private void updateShaderMatrix() {
  167. float scale;
  168. float dx = 0;
  169. float dy = 0;
  170. mShaderMatrix.set(null);
  171. if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
  172. scale = mDrawableRect.height() / (float) mBitmapHeight;
  173. dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
  174. } else {
  175. scale = mDrawableRect.width() / (float) mBitmapWidth;
  176. dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
  177. }
  178. mShaderMatrix.setScale(scale, scale);
  179. mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);
  180. mBitmapShader.setLocalMatrix(mShaderMatrix);
  181. }
  182. }

自定义的属性: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>

使用时的布局文件:

  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. <de.hdodenhof.circleimageview.CircleImageView
  14. android:layout_width="160dp"
  15. android:layout_height="160dp"
  16. android:layout_centerInParent="true"
  17. android:src="@drawable/demo"
  18. app:border_width="2dp"
  19. app:border_color="@color/dark" />
  20. </RelativeLayout>
  21. <RelativeLayout
  22. android:layout_width="match_parent"
  23. android:layout_height="0dp"
  24. android:layout_weight="1"
  25. android:padding="@dimen/base_padding"
  26. android:background="@color/dark">
  27. <de.hdodenhof.circleimageview.CircleImageView
  28. android:layout_width="160dp"
  29. android:layout_height="160dp"
  30. android:layout_centerInParent="true"
  31. android:src="@drawable/lena"
  32. app:border_width="2dp"
  33. app:border_color="@color/light" />
  34. </RelativeLayout>
  35. </LinearLayout>

效果:

Center

Demo下载:http://download.csdn.net/detail/nuptboyzhb/7284553

注意:有些开发者可能也发现了,如果我们需要一个圆形的ImageButton的话,其实,我们没有必要自己写。如果ImageButton的图标是固定不变的,我们完全可以让设计师给我设计一个圆形的图片,然后直接设置再ImageButton上就可以了。但是,请注意,我们这里的圆形ImageView是自定义控件,也即是:无论你设置的图片是什么样的,显示出来的就是圆的。比如:易信中用户头像的设置,无论用户拍什么的照片,显示出来都是一个圆的。

拓展阅读

还有一个更加强大的RoundedImageView,还支持圆角,椭圆等等。

https://github.com/vinc3m1/RoundedImageView

发表评论

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

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

相关阅读