Skip to content

Instantly share code, notes, and snippets.

@SiddheshShetye
Last active August 29, 2015 14:01
Show Gist options
  • Save SiddheshShetye/c4146fa28f8e73fac778 to your computer and use it in GitHub Desktop.
Save SiddheshShetye/c4146fa28f8e73fac778 to your computer and use it in GitHub Desktop.
RoundImageView is derived from RoundedCornerNetworkImageView which is not dependent on NetworkImageView From Volley.
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2013 Siddhesh S Shetye
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<declare-styleable name="RoundImageView">
<!-- true for circular imageview -->
<attr name="isCircular" format="boolean" />
<!-- radius for circular edges of imageview -->
<attr name="radius" format="integer" />
<!-- margin for imageview -->
<attr name="margin" format="integer" />
<!-- true for drawing shadow on imageview -->
<attr name="isShadowPresent" format="boolean" />
<!-- specify color for the circular border -->
<attr name="circleColor" format="color"/>
<!-- true to draw circular border -->
<attr name="drawCircle" format="boolean"/>
</declare-styleable>
</resources>
/*
* Copyright (C) 2013 Siddhesh S Shetye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
/**
* The Class RoundImageView.<br/>
* <code>RoundImageView</code><br/> Is a Custom <code>ImageView</code> class.<br/> which
* provides all the functionalities of rounded edges for the <code>ImageView</code> with gradient effect.<br/>
* This Class is dependent on StreamDrawable from <b>RomainGuy</b> in his Image With Rounded Corners Demo but with little modifications.
* @author siddhesh
* @version 1.2
* @see <a href ="https://android.googlesource.com/platform/frameworks/volley">Volley<a/>
* @see <a href ="https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/NetworkImageView.java">NetworkImageView<a/>
* @see <a href ="http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/">Rounded Corner Images<a/>
*/
public class RoundImageView extends ImageView{
/** The m radius. */
private int mRadius;
/** The is circular. */
private boolean isCircular;
/** The drawable. */
private StreamDrawable mDrawable;
/** The m margin. */
private int mMargin;
/** The is shadowed. */
private boolean isShadowed;
/** The m circle paint. */
private Paint mCirclePaint;
/** The draw circle. */
private boolean drawCircle;
/** The m circle color. */
private int mCircleColor;
/**
* Instantiates a new round image view.
*
* @param context the context
*/
public RoundImageView(Context context) {
this(context,null);
}
/**
* Instantiates a new round image view.
*
* @param context the context
* @param attrs the attrs
*/
public RoundImageView(Context context,AttributeSet attrs) {
this(context,attrs,0);
}
/**
* Instantiates a new round image view.
*
* @param context the context
* @param attribs the attribs
* @param def the def
*/
public RoundImageView(Context context,AttributeSet attribs,int def) {
super(context,attribs,def);
TypedArray a=getContext().obtainStyledAttributes(
attribs,
R.styleable.RoundImageView);
mRadius = a.getInt(
R.styleable.RoundImageView_radius,4);
mMargin = a.getInt(
R.styleable.RoundImageView_margin,0);
isCircular = a.getBoolean(R.styleable.RoundImageView_isCircular, false);
isShadowed = a.getBoolean(
R.styleable.RoundImageView_isShadowPresent,false);
drawCircle = a.getBoolean(R.styleable.RoundImageView_drawCircle, false);
mCircleColor = a.getColor(R.styleable.RoundImageView_circleColor, Color.WHITE);
int src_resource = attribs.getAttributeResourceValue("http://schemas.android.com/apk/res/android", "src",0);
if(src_resource != 0)
setImageResource(src_resource);
a.recycle();
mCirclePaint = new Paint();
mCirclePaint.setStrokeWidth(4f);
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStyle(Style.STROKE);
if(isCircular)
isShadowed = false;
}
/**
* Sets the radius.
*
* @param radius the new radius
*/
public void setRadius(int radius){
mRadius = radius;
}
/**
* Sets the isCircular.
*
* @param isCircular true for circular ImageView
*/
public void setCircular(boolean isCircular){
this.isCircular = isCircular;
}
/**
* Gets the radius.
*
* @return the radius
*/
public int getRadius() {
return mRadius;
}
/**
* Checks if is circular.
*
* @return true, if is circular
*/
public boolean isCircular() {
return isCircular;
}
/**
* Gets the margin.
*
* @return the m margin
*/
public int getmMargin() {
return mMargin;
}
/**
* Sets the margin.
*
* @param margin the new margin
*/
public void setmMargin(int margin) {
this.mMargin = margin;
}
/* (non-Javadoc)
* @see android.widget.ImageView#onDraw(android.graphics.Canvas)
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(isCircular && drawCircle)
canvas.drawCircle((this.getWidth()*1.0f)/2, (this.getHeight()*1.0f)/2, (this.getHeight()*1.0f)/2-1.8f, mCirclePaint);
}
/* (non-Javadoc)
* @see android.widget.ImageView#setImageBitmap(android.graphics.Bitmap)
*/
@Override
public void setImageBitmap(final Bitmap bm) {
if (bm != null) {
if(isCircular){
mRadius = (int) Math.max(this.getWidth()/2, this.getHeight()/2);
if(mRadius == 0){
ViewTreeObserver ob = getViewTreeObserver();
ob.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) @SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
mRadius = (int) Math.max(RoundImageView.this.getWidth()/2, RoundImageView.this.getHeight()/2);
mDrawable = new StreamDrawable(bm, mRadius, mMargin,isShadowed,RoundImageView.this.getScaleType());
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
getViewTreeObserver().removeGlobalOnLayoutListener(this);
else
getViewTreeObserver().removeOnGlobalLayoutListener(this);
RoundImageView.super.setImageDrawable(mDrawable);
}
});
}else{
mDrawable = new StreamDrawable(bm, mRadius, mMargin,isShadowed,this.getScaleType());
super.setImageDrawable(mDrawable);
}
}else{
mDrawable = new StreamDrawable(bm, mRadius, mMargin,isShadowed,this.getScaleType());
super.setImageDrawable(mDrawable);
}
} else {
mDrawable = null;
}
}
/* (non-Javadoc)
* @see android.widget.ImageView#setImageResource(int)
*/
@Override
public void setImageResource(int resId) {
setImageBitmap(BitmapFactory.decodeResource(getResources(), resId));
}
/* (non-Javadoc)
* @see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
*/
@Override
public void setImageDrawable(Drawable drawable) {
if(drawable == null){
return;
}
if(drawable instanceof BitmapDrawable){
setImageBitmap(((BitmapDrawable)drawable).getBitmap());
}else if(drawable instanceof StreamDrawable){
super.setImageDrawable(drawable);
//TODO: CHECK AND ADD SUPPORT FOR COLOR DRAWABLE
}else{
int width = drawable.getIntrinsicWidth() == -1?60:drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight() == -1?60:drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
setImageBitmap(bitmap);
}
}
}
/*
* Copyright (C) 2013 Siddhesh S Shetye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ComposeShader;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.widget.ImageView.ScaleType;
/**
* The Class StreamDrawable.<br/>
* It is Derived class from Romain guy's Rounded Corner Images and m3n0r's Rounded Drawable
* @see <a href ="http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/">Rounded Corner Images<a/>
* @see <a href ="https://github.com/m3n0R/MenorImageView/blob/22b2af96f72cabddecc4a0612fbd90d4504a200f/MenorImageView/src/com/android/menorimageview/RoundedDrawable.java">RoundedDrawable<a/>
* @author siddhesh
* @version 1.2
*/
public class StreamDrawable extends Drawable {
/** The corner radius. */
private final float mCornerRadius;
private final BitmapShader mBitmapShader;
/** The paint. */
private final Paint mPaint;
/** The margin. */
private final int mMargin;
/** The is vignette. */
private boolean isVignette;
/** The scale type. */
private ScaleType mScaleType;
/** The shader matrix. */
private final Matrix mShaderMatrix = new Matrix();
/** The bounds. */
private final RectF mBounds = new RectF();
/** The drawable rect. */
private final RectF mDrawableRect = new RectF();
/** The bitmap rect. */
private final RectF mBitmapRect = new RectF();
/** The border rect. */
private final RectF mBorderRect = new RectF();
/** The bitmap width. */
private final int mBitmapWidth;
/** The bitmap height. */
private final int mBitmapHeight;
/**
* Instantiates a new stream drawable.
*
* @param bitmap the bitmap
* @param cornerRadius the corner radius
* @param margin the margin
* @param isVignette true for shadow on image
* @param scaleType the ScaleType
* @see android.widget.ImageView.ScaleType
*/
public StreamDrawable(Bitmap bitmap, float cornerRadius, int margin,boolean isVignette,ScaleType scaleType) {
if(scaleType == null)
scaleType = ScaleType.CENTER_INSIDE;
mScaleType = scaleType;
mBitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
mBitmapHeight = bitmap.getHeight();
mBitmapWidth = bitmap.getWidth();
mCornerRadius = cornerRadius;
this.isVignette = isVignette;
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapShader.setLocalMatrix(mShaderMatrix);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
mMargin = margin;
}
/* (non-Javadoc)
* @see android.graphics.drawable.Drawable#onBoundsChange(android.graphics.Rect)
*/
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBounds.set(bounds);
mBorderRect.set(bounds);
mDrawableRect.set(0 + mMargin, 0 + mMargin, mBorderRect.width() - mMargin, mBorderRect.height() - mMargin);
float scale;
float dx;
float dy;
switch (mScaleType) {
case FIT_CENTER:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.CENTER);
mShaderMatrix.mapRect(mBorderRect);
mDrawableRect.set(mBorderRect.left + mMargin, mBorderRect.top + mMargin, mBorderRect.right - mMargin, mBorderRect.bottom - mMargin);
mShaderMatrix.setRectToRect(mBitmapRect, mDrawableRect, Matrix.ScaleToFit.FILL);
break;
case CENTER:
mBorderRect.set(mBounds);
mDrawableRect.set(0 + mMargin, 0 + mMargin, mBorderRect.width() - mMargin, mBorderRect.height() - mMargin);
mShaderMatrix.set(null);
mShaderMatrix.setTranslate((int) ((mDrawableRect.width() - mBitmapWidth) * 0.5f + 0.5f), (int) ((mDrawableRect.height() - mBitmapHeight) * 0.5f + 0.5f));
break;
case CENTER_CROP:
mBorderRect.set(mBounds);
mDrawableRect.set(0 + mMargin, 0 + mMargin, mBorderRect.width() - mMargin, mBorderRect.height() - mMargin);
mShaderMatrix.set(null);
dx = 0;
dy = 0;
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
scale = (float) mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = (float) mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
break;
case CENTER_INSIDE:
mShaderMatrix.set(null);
if (mBitmapWidth <= mBounds.width() && mBitmapHeight <= mBounds.height()) {
scale = 1.0f;
} else {
scale = Math.min((float) mBounds.width() / (float) mBitmapWidth,
(float) mBounds.height() / (float) mBitmapHeight);
}
dx = (int) ((mBounds.width() - mBitmapWidth * scale) * 0.5f + 0.5f);
dy = (int) ((mBounds.height() - mBitmapHeight * scale) * 0.5f + 0.5f);
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate(dx, dy);
mBorderRect.set(mBitmapRect);
mShaderMatrix.mapRect(mBorderRect);
mDrawableRect.set(mBorderRect.left + mMargin, mBorderRect.top + mMargin, mBorderRect.right - mMargin, mBorderRect.bottom - mMargin);
mShaderMatrix.setRectToRect(mBitmapRect, mDrawableRect, Matrix.ScaleToFit.FILL);
break;
case FIT_END:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.END);
mShaderMatrix.mapRect(mBorderRect);
mDrawableRect.set(mBorderRect.left + mMargin, mBorderRect.top + mMargin, mBorderRect.right - mMargin, mBorderRect.bottom - mMargin);
mShaderMatrix.setRectToRect(mBitmapRect, mDrawableRect, Matrix.ScaleToFit.FILL);
break;
case FIT_START:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.START);
mShaderMatrix.mapRect(mBorderRect);
mDrawableRect.set(mBorderRect.left + mMargin, mBorderRect.top + mMargin, mBorderRect.right - mMargin, mBorderRect.bottom - mMargin);
mShaderMatrix.setRectToRect(mBitmapRect, mDrawableRect, Matrix.ScaleToFit.FILL);
break;
case FIT_XY:
mBorderRect.set(mBounds);
mDrawableRect.set(0 + mMargin, 0 + mMargin, mBorderRect.width() - mMargin, mBorderRect.height() - mMargin);
mShaderMatrix.set(null);
mShaderMatrix.setRectToRect(mBitmapRect, mDrawableRect, Matrix.ScaleToFit.FILL);
break;
case MATRIX:
break;
default:
mDrawableRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
break;
}
mBitmapShader.setLocalMatrix(mShaderMatrix);
if (isVignette) {
RadialGradient vignette = new RadialGradient(
mDrawableRect.centerX(), mDrawableRect.centerY() * 1.0f / 0.7f, mDrawableRect.centerX() * 1.9f,
new int[] { 0, 0, 0x7f000000 }, new float[] { 0.0f, 0.7f, 1.0f },
Shader.TileMode.CLAMP);
Matrix oval = new Matrix();
oval.setScale(1.0f, 0.7f);
vignette.setLocalMatrix(oval);
mPaint.setShader(
new ComposeShader(mBitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
}
}
/* (non-Javadoc)
* @see android.graphics.drawable.Drawable#draw(android.graphics.Canvas)
*/
@Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mDrawableRect, mCornerRadius, mCornerRadius, mPaint);
}
/* (non-Javadoc)
* @see android.graphics.drawable.Drawable#getOpacity()
*/
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
/* (non-Javadoc)
* @see android.graphics.drawable.Drawable#setAlpha(int)
*/
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
/* (non-Javadoc)
* @see android.graphics.drawable.Drawable#setColorFilter(android.graphics.ColorFilter)
*/
@Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment