Skip to content

Instantly share code, notes, and snippets.

@SiddheshShetye
Last active January 25, 2017 22:23
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SiddheshShetye/7923533 to your computer and use it in GitHub Desktop.
Save SiddheshShetye/7923533 to your computer and use it in GitHub Desktop.
NetworkImageView Is a Custom ImageView class.Provides all the functionalities of NetworkImageView from Volley. In addition to those this class provides functionality of rounded edges for the ImageView with gradient effect.This Class is dependent on StreamDrawable from RomainGuy in his Image With Rounded Corners Demo but with little modifications.
<?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="RoundedCornerNetworkImageView">
<!-- 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.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.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import com.android.volley.toolbox.NetworkImageView;
/**
* The Class RoundedCornerNetworkImageView.<br/>
* <code>RoundedCornerNetworkImageView extends NetworkImageView</code><br/> Is a Custom <code>ImageView</code> class.<br/>
* provides all the functionalities of <code>NetworkImageView</code> from <a href ="https://android.googlesource.com/platform/frameworks/volley">Volley</a><br/>
* In addition to those this class provides functionality 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 RoundedCornerNetworkImageView extends NetworkImageView{
/** 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;
private Paint mCirclePaint;
private boolean drawCircle;
private int mCircleColor;
/**
* Instantiates a new rounded corner network image view.<br/>
* Initializes <code>RoundedCornerNetworkImageView</code> with default radius of 4px, margin 0px and with no shadowing.
*
* @param context the context
*/
public RoundedCornerNetworkImageView(Context context) {
super(context);
mRadius = 4;
mMargin = 0;
isCircular = false;
isShadowed = false;
drawCircle = false;
mCircleColor = Color.WHITE;
setWillNotDraw(false);
mCirclePaint = new Paint();
mCirclePaint.setStrokeWidth(4f);
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStyle(Style.STROKE);
if(isCircular)
isShadowed = false;
}
/**
* Instantiates a new rounded corner network image view.
* Initializes <code>RoundedCornerNetworkImageView</code> with radius provided in <code>radius</code> attribute in <code>XML</code> or default 4px,<br/> margin with <code>radius</code> attribute in <code>XML</code> default 0px,<br/>
* if <code>isShadowing</code> attribute is true shadows will be drawn on image <br/>and if <code>isCircular</code> attribute is true radius will be ignored and a circular image will be drawn.
*
* @param context the context
* @param attribs the AttributeSet
*/
public RoundedCornerNetworkImageView(Context context,AttributeSet attribs) {
super(context, attribs);
TypedArray a=getContext().obtainStyledAttributes(
attribs,
R.styleable.RoundedCornerNetworkImageView);
mRadius = a.getInt(
R.styleable.RoundedCornerNetworkImageView_radius,4);
mMargin = a.getInt(
R.styleable.RoundedCornerNetworkImageView_margin,0);
isShadowed = a.getBoolean(
R.styleable.RoundedCornerNetworkImageView_isShadowPresent,false);
isCircular = a.getBoolean(R.styleable.RoundedCornerNetworkImageView_isCircular, false);
drawCircle = a.getBoolean(R.styleable.RoundedCornerNetworkImageView_drawCircle, false);
mCircleColor = a.getColor(R.styleable.RoundedCornerNetworkImageView_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();
if(isCircular)
isShadowed = false;
setWillNotDraw(false);
mCirclePaint = new Paint();
mCirclePaint.setStrokeWidth(4f);
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStyle(Style.STROKE);
}
/**
* Instantiates a new rounded corner network image view.
* Initializes <code>RoundedCornerNetworkImageView</code> with radius provided in <code>radius</code> attribute in <code>XML</code> or default 4px,<br/> margin with <code>radius</code> attribute in <code>XML</code> default 0px,<br/>
* if <code>isShadowing</code> attribute is true shadows will be drawn on image, <br/>if <code>isCircular</code> attribute is true radius will be ignored and a circular image will be drawn.<br/>
* and with defStyle provided.
* @param context the context
* @param attribs the AttributeSet
* @param defStyle the defStyle
*/
public RoundedCornerNetworkImageView(Context context,AttributeSet attribs,int defStyle) {
super(context, attribs, defStyle);
TypedArray a=getContext().obtainStyledAttributes(
attribs,
R.styleable.RoundedCornerNetworkImageView);
mRadius = a.getInt(
R.styleable.RoundedCornerNetworkImageView_radius,4);
mMargin = a.getInt(
R.styleable.RoundedCornerNetworkImageView_margin,0);
isCircular = a.getBoolean(R.styleable.RoundedCornerNetworkImageView_isCircular, false);
isShadowed = a.getBoolean(
R.styleable.RoundedCornerNetworkImageView_isShadowPresent,false);
drawCircle = a.getBoolean(R.styleable.RoundedCornerNetworkImageView_drawCircle, false);
mCircleColor = a.getColor(R.styleable.RoundedCornerNetworkImageView_circleColor, Color.WHITE);
int src_resource = attribs.getAttributeResourceValue("http://schemas.android.com/apk/res/android", "src",R.drawable.user_thumbnail2);
if(src_resource != 0)
setImageResource(src_resource);
a.recycle();
setWillNotDraw(false);
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;
}
@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(Bitmap bm) {
Log.e("CAME IN SET IMAGE BITMAP");
if (bm != null) {
Log.e("CAME IN BITMAP NOT NULL");
if(isCircular){
mRadius = (int) Math.max(this.getWidth()/2, this.getHeight()/2);
}
mDrawable = new StreamDrawable(bm, mRadius, mMargin,isShadowed,this.getScaleType());
} else {
Log.e("CAME IN BITMAP NULL");
mDrawable = null;
}
super.setImageDrawable(mDrawable);
}
@Override
public void setImageResource(int resId) {
setImageBitmap(BitmapFactory.decodeResource(getResources(), resId));
}
@Override
public void setImageDrawable(Drawable drawable) {
Log.e("CAME IN DRAWABLE");
if(drawable instanceof BitmapDrawable){
Log.e("CAME IN BITMAP DRAWABLE");
setImageBitmap(((BitmapDrawable)drawable).getBitmap());
}else if(drawable instanceof StreamDrawable){
Log.e("CAME IN STREAM DRAWABLE");
super.setImageDrawable(drawable);
}else if(drawable instanceof ColorDrawable){
Log.e("CAME IN COLOR DRAWABLE");
Bitmap bitmap = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
setImageBitmap(bitmap);
}else{
Log.e("CAME IN ELSE");
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), 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 Roman 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.1
*/
public class StreamDrawable extends Drawable {
/** The corner radius. */
private final float mCornerRadius;
/** The bitmap shader. */
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
*/
StreamDrawable(Bitmap bitmap, float cornerRadius, int margin,boolean isVignette,ScaleType scaleType) {
if(scaleType == null)
mScaleType = ScaleType.FIT_CENTER;
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:
Log.e("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:
Log.e("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:
Log.e("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:
Log.e("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:
Log.e("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:
Log.e("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:
Log.e("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:
Log.e("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);
}
}
@ravenet
Copy link

ravenet commented Aug 25, 2014

Hi,

There is an issue in your code below line,
int src_resource = attribs.getAttributeResourceValue("http://schemas.android.com/apk/res/android", "src",
R.drawable.user_thumbnail2);
Please check it

@nbozic-twisper
Copy link

It works fine to me.
Nice work!

@nnarendra
Copy link

working fine for me . Greate work....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment