android开源系列:CircleImageView自定义圆形控件的使用

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

package de.hdodenhof.circleimageview;
import edu.njupt.zhb.main.R;
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;

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);
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);
  }

}

自定义的属性:res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="border_width" format="dimension" />
<attr name="border_color" format="color" />
</declare-styleable>
</resources>

使用时的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="@dimen/base_padding"
android:background="@color/light">

<de.hdodenhof.circleimageview.CircleImageView
  android:layout_width="160dp"
  android:layout_height="160dp"
  android:layout_centerInParent="true"
  android:src="@drawable/demo"
  app:border_width="2dp"
  app:border_color="@color/dark" />

  </RelativeLayout>

  <RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="@dimen/base_padding"
android:background="@color/dark">

<de.hdodenhof.circleimageview.CircleImageView
  android:layout_width="160dp"
  android:layout_height="160dp"
  android:layout_centerInParent="true"
  android:src="@drawable/lena"
  app:border_width="2dp"
  app:border_color="@color/light" />

  </RelativeLayout>

</LinearLayout>

效果:


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,381评论 25 708
  • 山东水饺 星期天上午十点半 饿醒的我跑到了对街的饺子馆 一份猪肉香菇 一份韭菜馅 一碟花生米 外加两瓣大蒜 “老板...
    位长安阅读 290评论 2 0
  • 相比卡通,人物真的太难画了,我觉得自己有必要去系统的学学构图了…… 话说简书里不能放表情嘛?
    万水千山你陪我看阅读 415评论 28 8
  • 现如今,科技正以惊人的速度发展着。而科技衍生出的智能硬件要数智能手机普及度最高,影响最大。根据国际市场调研机构...
    General_Z阅读 242评论 0 0