Last active
March 7, 2016 19:33
-
-
Save r4hulp/74b97ace382757777199 to your computer and use it in GitHub Desktop.
Round ImageView extension for Xamarin Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Android.Content; | |
using Android.Content.Res; | |
using Android.Graphics; | |
using Android.Graphics.Drawables; | |
using Android.Util; | |
using Android.Views; | |
using Android.Widget; | |
namespace WrapCode.Util | |
{ | |
public class CircleImageView : ImageView | |
{ | |
private int borderWidth; | |
private int canvasSize; | |
private Bitmap image; | |
private Paint paint; | |
private Paint paintBorder; | |
public CircleImageView(Context context) | |
: this(context, null) | |
{ | |
} | |
public CircleImageView(Context context, IAttributeSet attrs) | |
: this(context, attrs, Resource.Attribute.circularImageViewStyle) | |
{ | |
} | |
public CircleImageView(Context context, IAttributeSet attrs, int defStyle) | |
: base(context, attrs, defStyle) | |
{ | |
// init paint | |
paint = new Paint(); | |
paint.AntiAlias = true; | |
paintBorder = new Paint(); | |
paintBorder.AntiAlias = true; | |
// load the styled attributes and set their properties | |
TypedArray attributes = context.ObtainStyledAttributes(attrs, Resource.Styleable.CircularImageView, defStyle, 0); | |
if (attributes.GetBoolean(Resource.Styleable.CircularImageView_border, true)) | |
{ | |
int defaultBorderSize = (int)(4 * context.Resources.DisplayMetrics.Density+ 0.5f); | |
BorderWidth = attributes.GetDimensionPixelOffset(Resource.Styleable.CircularImageView_border_width, defaultBorderSize); | |
BorderColor = attributes.GetColor(Resource.Styleable.CircularImageView_border_color, Color.White); | |
} | |
if (attributes.GetBoolean(Resource.Styleable.CircularImageView_shadow, false)) | |
{ | |
addShadow(); | |
} | |
} | |
public void addShadow() | |
{ | |
SetLayerType(LayerType.Software, paintBorder); | |
paintBorder.SetShadowLayer(4.0f, 0.0f, 2.0f, Color.Gray); | |
} | |
public virtual int BorderWidth | |
{ | |
set | |
{ | |
this.borderWidth = 5; | |
this.RequestLayout(); | |
this.Invalidate(); | |
} | |
} | |
public virtual int BorderColor | |
{ | |
set | |
{ | |
if (paintBorder != null) | |
{ | |
paintBorder.Color = Color.Gray; | |
} | |
this.Invalidate(); | |
} | |
} | |
protected override void OnDraw(Canvas canvas) | |
{ | |
// load the bitmap | |
image = drawableToBitmap(Drawable); | |
// init shader | |
if (image != null) | |
{ | |
canvasSize = canvas.Width; | |
if (canvas.Height < canvasSize) | |
{ | |
canvasSize = canvas.Height; | |
} | |
BitmapShader shader = new BitmapShader(Bitmap.CreateScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.Clamp, Shader.TileMode.Clamp); | |
paint.SetShader(shader); | |
int circleCenter = (canvasSize - (borderWidth * 2)) / 2; | |
canvas.DrawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder); | |
canvas.DrawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint); | |
} | |
} | |
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) | |
{ | |
int width = measureWidth(widthMeasureSpec); | |
int height = measureHeight(heightMeasureSpec); | |
SetMeasuredDimension(width, height); | |
} | |
private int measureWidth(int measureSpec) | |
{ | |
int result = 0; | |
var specMode = MeasureSpec.GetMode(measureSpec); | |
var specSize = MeasureSpec.GetSize(measureSpec); | |
if (specMode == MeasureSpecMode.Exactly) | |
{ | |
// The parent has determined an exact size for the child. | |
result = specSize; | |
} | |
else if (specMode == MeasureSpecMode.AtMost) | |
{ | |
// The child can be as large as it wants up to the specified size. | |
result = specSize; | |
} | |
else | |
{ | |
// The parent has not imposed any constraint on the child. | |
result = canvasSize; | |
} | |
return result; | |
} | |
private int measureHeight(int measureSpecHeight) | |
{ | |
int result = 0; | |
var specMode = MeasureSpec.GetMode(measureSpecHeight); | |
int specSize = MeasureSpec.GetSize(measureSpecHeight); | |
if (specMode == MeasureSpecMode.Exactly) | |
{ | |
// We were told how big to be | |
result = specSize; | |
} | |
else if (specMode == MeasureSpecMode.AtMost) | |
{ | |
// The child can be as large as it wants up to the specified size. | |
result = specSize; | |
} | |
else | |
{ | |
// Measure the text (beware: ascent is a negative number) | |
result = canvasSize; | |
} | |
return (result + 2); | |
} | |
public virtual Bitmap drawableToBitmap(Drawable drawable) | |
{ | |
if (drawable == null) | |
{ | |
return null; | |
} | |
else if (drawable is BitmapDrawable) | |
{ | |
return ((BitmapDrawable)drawable).Bitmap; | |
} | |
Bitmap bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888); | |
Canvas canvas = new Canvas(bitmap); | |
drawable.SetBounds(0, 0, canvas.Width, canvas.Height); | |
drawable.Draw(canvas); | |
return bitmap; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment