Android自定义控件之圆形头像

重写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(final Context context) {
      super(context);
   }

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

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

      final 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(final ScaleType scaleType) {
      if (scaleType != SCALE_TYPE) {
         throw new IllegalArgumentException(String.format(
               "ScaleType %s not supported.", scaleType));
      }
   }

   @Override
   protected void onDraw(final 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(final int w, final int h, final int oldw,
         final int oldh) {
      super.onSizeChanged(w, h, oldw, oldh);
      setup();
   }

   public int getBorderColor() {
      return mBorderColor;
   }

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

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

   public int getBorderWidth() {
      return mBorderWidth;
   }

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

      mBorderWidth = borderWidth;
      setup();
   }

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

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

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

   private Bitmap getBitmapFromDrawable(final 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);
         }

         final Canvas canvas = new Canvas(bitmap);
         drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
         drawable.draw(canvas);
         return bitmap;
      } catch (final 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() / mBitmapHeight;
         dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
      } else {
         scale = mDrawableRect.width() / 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);
   }

}

使用方法:

在布局文件中

    android:id="@+id/iv_avatar"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:src="@drawable/avatar"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"/>

效果图 

Android自定义控件之圆形头像_第1张图片





你可能感兴趣的:(Android开发)