Custom ImageView with drop shadow - android

Okay, I've been reading and searching around, and am now banging my head against the wall trying to figure this out. Here's what I have so far:
package com.pockdroid.sandbox;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.widget.ImageView;
public class ShadowImageView extends ImageView {
private Rect mRect;
private Paint mPaint;
public ShadowImageView(Context context)
{
super(context);
mRect = new Rect();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShadowLayer(2f, 1f, 1f, Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas)
{
Rect r = mRect;
Paint paint = mPaint;
canvas.drawRect(r, paint);
super.onDraw(canvas);
}
#Override
protected void onMeasure(int w, int h)
{
super.onMeasure(w,h);
int mH, mW;
mW = getSuggestedMinimumWidth() < getMeasuredWidth()? getMeasuredWidth() : getSuggestedMinimumWidth();
mH = getSuggestedMinimumHeight() < getMeasuredHeight()? getMeasuredHeight() : getSuggestedMinimumHeight();
setMeasuredDimension(mW + 5, mH + 5);
}
}
The "+5" in the measurements are there as temporary; From what I understand I'll need to do some math to determine the size that the drop shadow adds to the canvas, right?
But when I use this:
public View getView(int position, View convertView, ViewGroup parent) {
ShadowImageView sImageView;
if (convertView == null) {
sImageView = new ShadowImageView(mContext);
GridView.LayoutParams lp = new GridView.LayoutParams(85, 85);
sImageView.setLayoutParams(lp);
sImageView.setScaleType(ImageView.ScaleType.CENTER);
sImageView.setPadding(5,5,5,5);
} else {
sImageView = (ShadowImageView) convertView;
}
sImageView.setImageBitmap(bitmapList.get(position));
return sImageView;
}
in my ImageView, I still get just a normal ImageView when I run the program.
Any thoughts? Thanks.
EDIT: So I spoke with RomainGuy some in the IRC channel, and I have it working now for plain rectangular images with the below code. It still won't draw the shadow directly to my bitmap's transparency though, so I'm still working on that.
#Override
protected void onDraw(Canvas canvas)
{
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.omen);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShadowLayer(5.5f, 6.0f, 6.0f, Color.BLACK);
canvas.drawColor(Color.GRAY);
canvas.drawRect(50, 50, 50 + bmp.getWidth(), 50 + bmp.getHeight(), paint);
canvas.drawBitmap(bmp, 50, 50, null);
}

Okay, I don't foresee any more answers on this one, so what I ended up going with for now is just a solution for rectangular images. I've used the following NinePatch:
along with the appropriate padding in XML:
<ImageView
android:id="#+id/image_test"
android:background="#drawable/drop_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6px"
android:paddingTop="4px"
android:paddingRight="8px"
android:paddingBottom="9px"
android:src="#drawable/pic1"
/>
to get a fairly good result:
Not ideal, but it'll do.

This is taken from Romain Guy's presentation at Devoxx, pdf found here.
Paint mShadow = new Paint();
// radius=10, y-offset=2, color=black
mShadow.setShadowLayer(10.0f, 0.0f, 2.0f, 0xFF000000);
// in onDraw(Canvas)
canvas.drawBitmap(bitmap, 0.0f, 0.0f, mShadow);
NOTES
Don't forget for Honeycomb and above you need to invoke
setLayerType(LAYER_TYPE_SOFTWARE, mShadow), otherwise you will not see your shadow! (#Dmitriy_Boichenko)
SetShadowLayer does
not work with hardware acceleration unfortunately so it greatly
reduces performances (#Matt Wear) [1] [2]

I believe this answer from UIFuel
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#30CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#50CCCCCC" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="#color/white" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>

My dirty solution:
private static Bitmap getDropShadow3(Bitmap bitmap) {
if (bitmap==null) return null;
int think = 6;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int newW = w - (think);
int newH = h - (think);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(w, h, conf);
Bitmap sbmp = Bitmap.createScaledBitmap(bitmap, newW, newH, false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c = new Canvas(bmp);
// Right
Shader rshader = new LinearGradient(newW, 0, w, 0, Color.GRAY, Color.LTGRAY, Shader.TileMode.CLAMP);
paint.setShader(rshader);
c.drawRect(newW, think, w, newH, paint);
// Bottom
Shader bshader = new LinearGradient(0, newH, 0, h, Color.GRAY, Color.LTGRAY, Shader.TileMode.CLAMP);
paint.setShader(bshader);
c.drawRect(think, newH, newW , h, paint);
//Corner
Shader cchader = new LinearGradient(0, newH, 0, h, Color.LTGRAY, Color.LTGRAY, Shader.TileMode.CLAMP);
paint.setShader(cchader);
c.drawRect(newW, newH, w , h, paint);
c.drawBitmap(sbmp, 0, 0, null);
return bmp;
}
result:

Here you are. Set source of ImageView statically in xml or dynamically in code.
Shadow is here white.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<View android:layout_width="wrap_content" android:layout_height="wrap_content"
android:background="#android:color/white" android:layout_alignLeft="#+id/image"
android:layout_alignRight="#id/image" android:layout_alignTop="#id/image"
android:layout_alignBottom="#id/image" android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp" />
<ImageView android:id="#id/image" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:src="..."
android:padding="5dp" />
</RelativeLayout>

I manage to apply gradient border using this code..
public static Bitmap drawShadow(Bitmap bitmap, int leftRightThk, int bottomThk, int padTop) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int newW = w - (leftRightThk * 2);
int newH = h - (bottomThk + padTop);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(w, h, conf);
Bitmap sbmp = Bitmap.createScaledBitmap(bitmap, newW, newH, false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c = new Canvas(bmp);
// Left
int leftMargin = (leftRightThk + 7)/2;
Shader lshader = new LinearGradient(0, 0, leftMargin, 0, Color.TRANSPARENT, Color.BLACK, TileMode.CLAMP);
paint.setShader(lshader);
c.drawRect(0, padTop, leftMargin, newH, paint);
// Right
Shader rshader = new LinearGradient(w - leftMargin, 0, w, 0, Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);
paint.setShader(rshader);
c.drawRect(newW, padTop, w, newH, paint);
// Bottom
Shader bshader = new LinearGradient(0, newH, 0, bitmap.getHeight(), Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);
paint.setShader(bshader);
c.drawRect(leftMargin -3, newH, newW + leftMargin + 3, bitmap.getHeight(), paint);
c.drawBitmap(sbmp, leftRightThk, 0, null);
return bmp;
}

This works for me ...
public class ShadowImage extends Drawable {
Bitmap bm;
#Override
public void draw(Canvas canvas) {
Paint mShadow = new Paint();
Rect rect = new Rect(0,0,bm.getWidth(), bm.getHeight());
mShadow.setAntiAlias(true);
mShadow.setShadowLayer(5.5f, 4.0f, 4.0f, Color.BLACK);
canvas.drawRect(rect, mShadow);
canvas.drawBitmap(bm, 0.0f, 0.0f, null);
}
public ShadowImage(Bitmap bitmap) {
super();
this.bm = bitmap;
} ... }

Here the Implementation of Paul Burkes answer:
public class ShadowImageView extends ImageView {
public ShadowImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ShadowImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ShadowImageView(Context context) {
super(context);
}
private Paint createShadow() {
Paint mShadow = new Paint();
float radius = 10.0f;
float xOffset = 0.0f;
float yOffset = 2.0f;
// color=black
int color = 0xFF000000;
mShadow.setShadowLayer(radius, xOffset, yOffset, color);
return mShadow;
}
#Override
protected void onDraw(Canvas canvas) {
Paint mShadow = createShadow();
Drawable d = getDrawable();
if (d != null){
setLayerType(LAYER_TYPE_SOFTWARE, mShadow);
Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
canvas.drawBitmap(bitmap, 0.0f, 0.0f, mShadow);
} else {
super.onDraw(canvas);
}
};
}
TODO:
execute setLayerType(LAYER_TYPE_SOFTWARE, mShadow); only if API Level is > 10

I've built upon the answer above - https://stackoverflow.com/a/11155031/2060486 - to create a shadow around ALL sides..
private static final int GRAY_COLOR_FOR_SHADE = Color.argb(50, 79, 79, 79);
// this method takes a bitmap and draws around it 4 rectangles with gradient to create a
// shadow effect.
public static Bitmap addShadowToBitmap(Bitmap origBitmap) {
int shadowThickness = 13; // can be adjusted as needed
int bmpOriginalWidth = origBitmap.getWidth();
int bmpOriginalHeight = origBitmap.getHeight();
int bigW = bmpOriginalWidth + shadowThickness * 2; // getting dimensions for a bigger bitmap with margins
int bigH = bmpOriginalHeight + shadowThickness * 2;
Bitmap containerBitmap = Bitmap.createBitmap(bigW, bigH, Bitmap.Config.ARGB_8888);
Bitmap copyOfOrigBitmap = Bitmap.createScaledBitmap(origBitmap, bmpOriginalWidth, bmpOriginalHeight, false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas canvas = new Canvas(containerBitmap); // drawing the shades on the bigger bitmap
//right shade - direction of gradient is positive x (width)
Shader rightShader = new LinearGradient(bmpOriginalWidth, 0, bigW, 0, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(rightShader);
canvas.drawRect(bigW - shadowThickness, shadowThickness, bigW, bigH - shadowThickness, paint);
//bottom shade - direction is positive y (height)
Shader bottomShader = new LinearGradient(0, bmpOriginalHeight, 0, bigH, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(bottomShader);
canvas.drawRect(shadowThickness, bigH - shadowThickness, bigW - shadowThickness, bigH, paint);
//left shade - direction is negative x
Shader leftShader = new LinearGradient(shadowThickness, 0, 0, 0, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(leftShader);
canvas.drawRect(0, shadowThickness, shadowThickness, bigH - shadowThickness, paint);
//top shade - direction is negative y
Shader topShader = new LinearGradient(0, shadowThickness, 0, 0, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(topShader);
canvas.drawRect(shadowThickness, 0, bigW - shadowThickness, shadowThickness, paint);
// starting to draw bitmap not from 0,0 to get margins for shade rectangles
canvas.drawBitmap(copyOfOrigBitmap, shadowThickness, shadowThickness, null);
return containerBitmap;
}
Change the color in the const as you see fit.

Use this class to draw shadow on bitmaps
public class ShadowGenerator {
// Percent of actual icon size
private static final float HALF_DISTANCE = 0.5f;
public static final float BLUR_FACTOR = 0.5f/48;
// Percent of actual icon size
private static final float KEY_SHADOW_DISTANCE = 1f/48;
public static final int KEY_SHADOW_ALPHA = 61;
public static final int AMBIENT_SHADOW_ALPHA = 30;
private static final Object LOCK = new Object();
// Singleton object guarded by {#link #LOCK}
private static ShadowGenerator sShadowGenerator;
private int mIconSize;
private final Canvas mCanvas;
private final Paint mBlurPaint;
private final Paint mDrawPaint;
private final Context mContext;
private ShadowGenerator(Context context) {
mContext = context;
mIconSize = Utils.convertDpToPixel(context,63);
mCanvas = new Canvas();
mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
mBlurPaint.setMaskFilter(new BlurMaskFilter(mIconSize * BLUR_FACTOR, Blur.NORMAL));
mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
}
public synchronized Bitmap recreateIcon(Bitmap icon) {
mIconSize = Utils.convertDpToPixel(mContext,3)+icon.getWidth();
int[] offset = new int[2];
Bitmap shadow = icon.extractAlpha(mBlurPaint, offset);
Bitmap result = Bitmap.createBitmap(mIconSize, mIconSize, Config.ARGB_8888);
mCanvas.setBitmap(result);
// Draw ambient shadow
mDrawPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
mCanvas.drawBitmap(shadow, offset[0], offset[1], mDrawPaint);
// Draw key shadow
mDrawPaint.setAlpha(KEY_SHADOW_ALPHA);
mCanvas.drawBitmap(shadow, offset[0], offset[1] + KEY_SHADOW_DISTANCE * mIconSize, mDrawPaint);
// Draw the icon
mDrawPaint.setAlpha(255);
mCanvas.drawBitmap(icon, 0, 0, mDrawPaint);
mCanvas.setBitmap(null);
return result;
}
public static ShadowGenerator getInstance(Context context) {
synchronized (LOCK) {
if (sShadowGenerator == null) {
sShadowGenerator = new ShadowGenerator(context);
}
}
return sShadowGenerator;
}
}

If you want to use the custom imageView, I suggest you use this one
View look perfect and dont't use any nine path image

Related

display image from url in rounded imageview android

I want to display my images in listview where the imageview is rounded, i serached in the net and in stackoverflow i just found that they use bitmap or i dont like to use it because i'm getting my information from webservice. is there any method or exemple to display it in this way.
this is how i display my images rectangle border
mLoader.DisplayImage(mylink + ArrayListComment.get(position).getImage(), holder.imageView);
}
if(ArrayListComment.get(position).getImage().contains(".png") {
mLoader.DisplayImage(ArrayListComment.get(position).getImage(), holder.imageView);
}
For rounded ImageView use RoundedImageView.
For display image from url use Picasso.
Create a new rounded.xml under drawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<stroke
android:width="10dp"
android:color="#FFffffff" />
<solid android:color="#00000000" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke
android:width="10dp"
android:color="#FFffffff" />
<solid android:color="#00000000" />
<corners android:radius="30dp" />
</shape>
</item>
</layer-list>
and use it in your xml image view like this:
android:src="#drawable/rounded" and set the image background as you want it to be, it will be in a rounded shape
I hope this will help
Yes, you can od it by customizing your Imageview. Please check out my customImageview class Which may help you.enter code here.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),
Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f,
sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
Try this,
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
public class ImageHelper {
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
You will have to customise your image loader.
EDIT:
If you dont want to create a copy of a bitmap, you can use a bitmap shader.
See this blog,
http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/
See the RoundedImageView for implementation.
Try this link
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if(bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(),
sbmp.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(sbmp.getWidth() / 2+0.7f, sbmp.getHeight() / 2+0.7f,
sbmp.getWidth() / 2+0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
http://easyandroidexample.blogspot.in/2015/03/how-to-make-image-circle-view.html
may it work for you

Cropping square image into circular image in android

I want a square image to be converted to circular image and displayed in the imageview. Image 1 is the required output, image two is the sqaure source image and image3 is the current output from the code pasted below. Code for cropping square image and than converting into circular image is pasted below. Please have a look at it and correct it.
private Bitmap cutCenterSquare(Bitmap bitmap) {
Bitmap origialBitmap = bitmap;
Bitmap cutBitmap = Bitmap.createBitmap(origialBitmap.getWidth() / 2,
origialBitmap.getHeight() / 2, Config.ARGB_8888);
Canvas canvas = new Canvas(cutBitmap);
Rect desRect = new Rect(0,0,(int)(imageview.getWidth()*0.94-imageview.getWidth()*0.06),(int)(imageview.getHeight()*0.725-imageview.getHeight()*0.16));
Rect srcRect = new Rect((int)(imageview.getWidth()*0.06),(int)(imageview.getHeight()*0.16),
(int)(imageview.getWidth()*0.94),
(int)(imageview.getHeight()*0.725));
canvas.drawBitmap(origialBitmap, srcRect, desRect, null);
return cutBitmap;
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if(bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(), Bitmap.Config.ARGB_8888);
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#646464"));
Canvas c = new Canvas(output);
c.drawARGB(0, 0, 0, 0);
c.drawCircle(sbmp.getWidth() / 2+0.7f, sbmp.getHeight() / 2+0.7f, sbmp.getWidth() / 2+0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
c.drawBitmap(sbmp, rect, rect, paint);
return output;
}
<ImageView
android:id="#+id/profile_image"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
android:layout_marginTop="24dp"
android:background="#drawable/background_circle"
android:contentDescription=""
android:scaleType="centerCrop"/>
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#646464"/>
<size
android:width="1dp"
android:height="1dp"/>
</shape>
Pay attention to your code. You are using 2 bitmaps in memory.
There is a very interesting post about image with rounded corners: http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
It is written by Romain Guy (ex android team at Google).
You can write a circular bitmap with a similar code:
public class CircleDrawable extends Drawable {
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private Paint mWhitePaint;
int circleCenterX;
int circleCenterY;
int mRadus;
private boolean mUseStroke = false;
private int mStrokePadding = 0;
public CircleDrawable(Bitmap bitmap) {
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
}
public CircleDrawable(Bitmap bitmap, boolean mUseStroke) {
this(bitmap);
if (mUseStroke) {
this.mUseStroke = true;
mStrokePadding = 4;
mWhitePaint = new Paint();
mWhitePaint.setStyle(Paint.Style.FILL_AND_STROKE);
mWhitePaint.setStrokeWidth(0.75f);
mWhitePaint.setColor(Color.WHITE);
}
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
circleCenterX = bounds.width() / 2;
circleCenterY = bounds.height() / 2;
if (bounds.width() >= bounds.height())
mRadus = bounds.width() / 2;
else
mRadus = bounds.height() / 2;
}
#Override
public void draw(Canvas canvas) {
if (mUseStroke) {
canvas.drawCircle(circleCenterX, circleCenterY, mRadus, mWhitePaint);
}
canvas.drawCircle(circleCenterX, circleCenterY, mRadus - mStrokePadding, mPaint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
public boolean ismUseStroke() {
return mUseStroke;
}
public void setmUseStroke(boolean mUseStroke) {
this.mUseStroke = mUseStroke;
}
}
To use it:
CircleDrawable circle = new CircleDrawable(bitmap,true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
imageView.setBackground(circle);
else
imageView.setBackgroundDrawable(circle);
You can take a look into this project in github. It provides a way to set an image in XML and programmatically, and displays a resizable circular crop window on top of the image. Calling the method getCroppedCircleImage() will then return the Circle Bitmap marked by the circular crop window.
Maybe this could come in handy.
CIrcleImageCropper
Sathya

How to make rounded Rectangle with two colors in progressbar?

I want to do multiple color progressbar with rounded rectangle progress.like below image
But I got result like below image of progressbar.
Here I am putting code of my customDrawable
public class FractionDrawable extends Drawable {
private Paint mPaint;
private int mTotalPercent;
private int mProgress1Percent;
private int mProgress1Color;
private int mProgress2Percent;
private int mProgress2Color;
private Context context;
public FractionDrawable(Context context,int totalPercent, int progress1Percent, int progress1Color, int progress2Percent, int progress2Color) {
mPaint = new Paint();
this.mTotalPercent = totalPercent;
this.mProgress1Percent = progress1Percent;
this.mProgress1Color = progress1Color;
this.mProgress2Percent = progress2Percent;
this.mProgress2Color = progress2Color;
this.context =context;
}
#Override
public void draw(Canvas canvas) {
Rect b = getBounds();
float totalProgWidth = b.width() * (mTotalPercent/100f);
float frac1Width = totalProgWidth * (mProgress1Percent/100f);
RectF rect = new RectF(0, 0, totalProgWidth, b.height());
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.BLACK);
canvas.drawRoundRect(rect, 18, 18, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mProgress1Color);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawRect(0, 0, frac1Width, b.height(), mPaint);
mPaint.setColor(mProgress2Color);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawRect(frac1Width, 0, totalProgWidth, b.height(), mPaint);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Try the following code and i implemented in my project. It works like a charm.
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#6dc518"
android:endColor="#10ffffff"
android:angle="180" />
<stroke
android:width="1dp"
android:color="#212122" />
<corners
android:radius="6dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
public class FractionDrawable extends Drawable {
private Paint mPaint;
private int mTotalPercent;
private int mProgress1Percent;
private int mProgress1Color;
private int mProgress2Percent;
private int mProgress2Color;
private Context context;
private Bitmap mSrcBCurve, mSrcDisplayRect;
private float radiusX = 15, radiusY = 15;
public FractionDrawable(Context context, int totalPercent, int progress1Percent, int progress1Color, int progress2Percent, int progress2Color) {
mPaint = new Paint();
this.mTotalPercent = totalPercent;
this.mProgress1Percent = progress1Percent;
this.mProgress1Color = progress1Color;
this.mProgress2Percent = progress2Percent;
this.mProgress2Color = progress2Color;
this.context = context;
}
#Override
public void draw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT);
Rect b = getBounds();
// determine the total progress width
float totalProgWidth = b.width() * (mTotalPercent / 100f);
// determine first progress width
float frac1Width = totalProgWidth * (mProgress1Percent / 100f);
mSrcBCurve = makeSrcRoundRectangle(0, 0, (int) totalProgWidth, b.height(),
(int) totalProgWidth, b.height(), radiusX, radiusY, mProgress1Color);
mSrcDisplayRect = makeSrcDisplayRectangle(context, 0, 0, (int) frac1Width,
b.height(), (int) frac1Width, b.height(), (int) totalProgWidth, mProgress1Color,
mProgress2Color, radiusX, radiusY);
int count = canvas.saveLayer(0, 0, (int) totalProgWidth, b.height(), null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG
);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setFilterBitmap(false);
canvas.drawBitmap(mSrcBCurve, 0, 0, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(mSrcDisplayRect, 0, 0, mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(count);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
private static Bitmap makeSrcDisplayRectangle(Context context, int left, int top, int right, int bottom, int width, int height, int secondWidth, int firstColor, int SecondColor, float radiusX, float radiusY) {
Bitmap bm = Bitmap.createBitmap(secondWidth, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(firstColor);
canvas.drawRect(left, top, right, bottom, mPaint);
mPaint.setColor(SecondColor);
canvas.drawRect(right, top, secondWidth, bottom, mPaint);
mPaint.setColor(Color.argb(40, 0, 0, 0));
canvas.drawRect(0, bottom - context.getResources().getInteger(R.integer.partiton3ddimen), secondWidth, bottom, mPaint);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
RectF rect = new RectF(left, top, secondWidth, bottom);
canvas.drawRoundRect(rect, radiusX, radiusY, mPaint);
return bm;
}
private static Bitmap makeSrcRoundRectangle(float left, float top, float right, float
bottom, int width, int height, float radiusX, float radiusY, int color) {
Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(color);
RectF rect = new RectF(left, top, right, bottom);
canvas.drawRoundRect(rect, radiusX, radiusY, mPaint);
return bm;
}
}

PorterDuff.Mode equivalent for edge fading

I want to programatically render the edge fading of a TextView. By which mode I can create a true alpha gradient?
A real edge fading should smoothly reduce the transparency (no overlay gradient hack) from 1.0 to 0.0 so that the top view fade into background view.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int y = 0;
int height = 300;
int width = getWidth();
LinearGradient shader = new LinearGradient(width / 2, y, width / 2, y + height, 0xff000000, 0x0000000, Shader.TileMode.CLAMP);
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XXX)); // Which mode works?
p.setShader(shader);
canvas.drawRect(0, y, width, y + height, p);
}
I tried all the combinations and none of them worked? Is it impossible to do so?
Here is my solution with an ImageView.
I use a GradientDrawable for the alpha.
Activity:
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawableResource(R.drawable.background);
GradientImageView giv = new GradientImageView(this);
giv.setImageResource(R.drawable.bttf);
giv.setScaleType(ImageView.ScaleType.CENTER_CROP);
setContentView(giv);
}
class GradientImageView extends ImageView
{
Drawable mDrawableMask;
Paint mPaintMask;
Bitmap mOriginal, mBitmapMask;
Canvas mCanvasOriginal, mCanvasMask;
public GradientImageView (final Context context)
{
super(context);
if (android.os.Build.VERSION.SDK_INT >= 11)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mDrawableMask = getResources().getDrawable(R.drawable.gradient);
mPaintMask = new Paint();
mPaintMask.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
protected void setMask (Drawable mask)
{
mDrawableMask = mask;
mBitmapMask = null;
}
#Override
protected void onDraw (final Canvas canvas)
{
if (mOriginal == null)
{
mOriginal = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mCanvasOriginal = new Canvas(mOriginal);
}
super.onDraw(mCanvasOriginal);
if (mBitmapMask == null)
{
mBitmapMask = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mCanvasMask = new Canvas(mBitmapMask);
mDrawableMask.setBounds(0, 0, getWidth(), getHeight());
mDrawableMask.draw(mCanvasMask);
}
canvas.drawBitmap(mOriginal, 0, 0, null);
canvas.drawBitmap(mBitmapMask, 0, 0, mPaintMask);
}
}
gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<gradient
android:angle="-90"
android:centerColor="#android:color/transparent"
android:centerY="0.5"
android:endColor="#android:color/black"
android:startColor="#android:color/transparent" />
values.xml
<drawable name="background">#FF0000</drawable>
The result (activity background is Red)

Change color of shadow for an ImageView on Android [duplicate]

Okay, I've been reading and searching around, and am now banging my head against the wall trying to figure this out. Here's what I have so far:
package com.pockdroid.sandbox;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.widget.ImageView;
public class ShadowImageView extends ImageView {
private Rect mRect;
private Paint mPaint;
public ShadowImageView(Context context)
{
super(context);
mRect = new Rect();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShadowLayer(2f, 1f, 1f, Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas)
{
Rect r = mRect;
Paint paint = mPaint;
canvas.drawRect(r, paint);
super.onDraw(canvas);
}
#Override
protected void onMeasure(int w, int h)
{
super.onMeasure(w,h);
int mH, mW;
mW = getSuggestedMinimumWidth() < getMeasuredWidth()? getMeasuredWidth() : getSuggestedMinimumWidth();
mH = getSuggestedMinimumHeight() < getMeasuredHeight()? getMeasuredHeight() : getSuggestedMinimumHeight();
setMeasuredDimension(mW + 5, mH + 5);
}
}
The "+5" in the measurements are there as temporary; From what I understand I'll need to do some math to determine the size that the drop shadow adds to the canvas, right?
But when I use this:
public View getView(int position, View convertView, ViewGroup parent) {
ShadowImageView sImageView;
if (convertView == null) {
sImageView = new ShadowImageView(mContext);
GridView.LayoutParams lp = new GridView.LayoutParams(85, 85);
sImageView.setLayoutParams(lp);
sImageView.setScaleType(ImageView.ScaleType.CENTER);
sImageView.setPadding(5,5,5,5);
} else {
sImageView = (ShadowImageView) convertView;
}
sImageView.setImageBitmap(bitmapList.get(position));
return sImageView;
}
in my ImageView, I still get just a normal ImageView when I run the program.
Any thoughts? Thanks.
EDIT: So I spoke with RomainGuy some in the IRC channel, and I have it working now for plain rectangular images with the below code. It still won't draw the shadow directly to my bitmap's transparency though, so I'm still working on that.
#Override
protected void onDraw(Canvas canvas)
{
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.omen);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShadowLayer(5.5f, 6.0f, 6.0f, Color.BLACK);
canvas.drawColor(Color.GRAY);
canvas.drawRect(50, 50, 50 + bmp.getWidth(), 50 + bmp.getHeight(), paint);
canvas.drawBitmap(bmp, 50, 50, null);
}
Okay, I don't foresee any more answers on this one, so what I ended up going with for now is just a solution for rectangular images. I've used the following NinePatch:
along with the appropriate padding in XML:
<ImageView
android:id="#+id/image_test"
android:background="#drawable/drop_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6px"
android:paddingTop="4px"
android:paddingRight="8px"
android:paddingBottom="9px"
android:src="#drawable/pic1"
/>
to get a fairly good result:
Not ideal, but it'll do.
This is taken from Romain Guy's presentation at Devoxx, pdf found here.
Paint mShadow = new Paint();
// radius=10, y-offset=2, color=black
mShadow.setShadowLayer(10.0f, 0.0f, 2.0f, 0xFF000000);
// in onDraw(Canvas)
canvas.drawBitmap(bitmap, 0.0f, 0.0f, mShadow);
NOTES
Don't forget for Honeycomb and above you need to invoke
setLayerType(LAYER_TYPE_SOFTWARE, mShadow), otherwise you will not see your shadow! (#Dmitriy_Boichenko)
SetShadowLayer does
not work with hardware acceleration unfortunately so it greatly
reduces performances (#Matt Wear) [1] [2]
I believe this answer from UIFuel
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#30CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#50CCCCCC" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="#color/white" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
My dirty solution:
private static Bitmap getDropShadow3(Bitmap bitmap) {
if (bitmap==null) return null;
int think = 6;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int newW = w - (think);
int newH = h - (think);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(w, h, conf);
Bitmap sbmp = Bitmap.createScaledBitmap(bitmap, newW, newH, false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c = new Canvas(bmp);
// Right
Shader rshader = new LinearGradient(newW, 0, w, 0, Color.GRAY, Color.LTGRAY, Shader.TileMode.CLAMP);
paint.setShader(rshader);
c.drawRect(newW, think, w, newH, paint);
// Bottom
Shader bshader = new LinearGradient(0, newH, 0, h, Color.GRAY, Color.LTGRAY, Shader.TileMode.CLAMP);
paint.setShader(bshader);
c.drawRect(think, newH, newW , h, paint);
//Corner
Shader cchader = new LinearGradient(0, newH, 0, h, Color.LTGRAY, Color.LTGRAY, Shader.TileMode.CLAMP);
paint.setShader(cchader);
c.drawRect(newW, newH, w , h, paint);
c.drawBitmap(sbmp, 0, 0, null);
return bmp;
}
result:
Here you are. Set source of ImageView statically in xml or dynamically in code.
Shadow is here white.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<View android:layout_width="wrap_content" android:layout_height="wrap_content"
android:background="#android:color/white" android:layout_alignLeft="#+id/image"
android:layout_alignRight="#id/image" android:layout_alignTop="#id/image"
android:layout_alignBottom="#id/image" android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp" />
<ImageView android:id="#id/image" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:src="..."
android:padding="5dp" />
</RelativeLayout>
I manage to apply gradient border using this code..
public static Bitmap drawShadow(Bitmap bitmap, int leftRightThk, int bottomThk, int padTop) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int newW = w - (leftRightThk * 2);
int newH = h - (bottomThk + padTop);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(w, h, conf);
Bitmap sbmp = Bitmap.createScaledBitmap(bitmap, newW, newH, false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c = new Canvas(bmp);
// Left
int leftMargin = (leftRightThk + 7)/2;
Shader lshader = new LinearGradient(0, 0, leftMargin, 0, Color.TRANSPARENT, Color.BLACK, TileMode.CLAMP);
paint.setShader(lshader);
c.drawRect(0, padTop, leftMargin, newH, paint);
// Right
Shader rshader = new LinearGradient(w - leftMargin, 0, w, 0, Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);
paint.setShader(rshader);
c.drawRect(newW, padTop, w, newH, paint);
// Bottom
Shader bshader = new LinearGradient(0, newH, 0, bitmap.getHeight(), Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);
paint.setShader(bshader);
c.drawRect(leftMargin -3, newH, newW + leftMargin + 3, bitmap.getHeight(), paint);
c.drawBitmap(sbmp, leftRightThk, 0, null);
return bmp;
}
This works for me ...
public class ShadowImage extends Drawable {
Bitmap bm;
#Override
public void draw(Canvas canvas) {
Paint mShadow = new Paint();
Rect rect = new Rect(0,0,bm.getWidth(), bm.getHeight());
mShadow.setAntiAlias(true);
mShadow.setShadowLayer(5.5f, 4.0f, 4.0f, Color.BLACK);
canvas.drawRect(rect, mShadow);
canvas.drawBitmap(bm, 0.0f, 0.0f, null);
}
public ShadowImage(Bitmap bitmap) {
super();
this.bm = bitmap;
} ... }
Here the Implementation of Paul Burkes answer:
public class ShadowImageView extends ImageView {
public ShadowImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ShadowImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ShadowImageView(Context context) {
super(context);
}
private Paint createShadow() {
Paint mShadow = new Paint();
float radius = 10.0f;
float xOffset = 0.0f;
float yOffset = 2.0f;
// color=black
int color = 0xFF000000;
mShadow.setShadowLayer(radius, xOffset, yOffset, color);
return mShadow;
}
#Override
protected void onDraw(Canvas canvas) {
Paint mShadow = createShadow();
Drawable d = getDrawable();
if (d != null){
setLayerType(LAYER_TYPE_SOFTWARE, mShadow);
Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
canvas.drawBitmap(bitmap, 0.0f, 0.0f, mShadow);
} else {
super.onDraw(canvas);
}
};
}
TODO:
execute setLayerType(LAYER_TYPE_SOFTWARE, mShadow); only if API Level is > 10
I've built upon the answer above - https://stackoverflow.com/a/11155031/2060486 - to create a shadow around ALL sides..
private static final int GRAY_COLOR_FOR_SHADE = Color.argb(50, 79, 79, 79);
// this method takes a bitmap and draws around it 4 rectangles with gradient to create a
// shadow effect.
public static Bitmap addShadowToBitmap(Bitmap origBitmap) {
int shadowThickness = 13; // can be adjusted as needed
int bmpOriginalWidth = origBitmap.getWidth();
int bmpOriginalHeight = origBitmap.getHeight();
int bigW = bmpOriginalWidth + shadowThickness * 2; // getting dimensions for a bigger bitmap with margins
int bigH = bmpOriginalHeight + shadowThickness * 2;
Bitmap containerBitmap = Bitmap.createBitmap(bigW, bigH, Bitmap.Config.ARGB_8888);
Bitmap copyOfOrigBitmap = Bitmap.createScaledBitmap(origBitmap, bmpOriginalWidth, bmpOriginalHeight, false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas canvas = new Canvas(containerBitmap); // drawing the shades on the bigger bitmap
//right shade - direction of gradient is positive x (width)
Shader rightShader = new LinearGradient(bmpOriginalWidth, 0, bigW, 0, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(rightShader);
canvas.drawRect(bigW - shadowThickness, shadowThickness, bigW, bigH - shadowThickness, paint);
//bottom shade - direction is positive y (height)
Shader bottomShader = new LinearGradient(0, bmpOriginalHeight, 0, bigH, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(bottomShader);
canvas.drawRect(shadowThickness, bigH - shadowThickness, bigW - shadowThickness, bigH, paint);
//left shade - direction is negative x
Shader leftShader = new LinearGradient(shadowThickness, 0, 0, 0, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(leftShader);
canvas.drawRect(0, shadowThickness, shadowThickness, bigH - shadowThickness, paint);
//top shade - direction is negative y
Shader topShader = new LinearGradient(0, shadowThickness, 0, 0, GRAY_COLOR_FOR_SHADE,
Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(topShader);
canvas.drawRect(shadowThickness, 0, bigW - shadowThickness, shadowThickness, paint);
// starting to draw bitmap not from 0,0 to get margins for shade rectangles
canvas.drawBitmap(copyOfOrigBitmap, shadowThickness, shadowThickness, null);
return containerBitmap;
}
Change the color in the const as you see fit.
Use this class to draw shadow on bitmaps
public class ShadowGenerator {
// Percent of actual icon size
private static final float HALF_DISTANCE = 0.5f;
public static final float BLUR_FACTOR = 0.5f/48;
// Percent of actual icon size
private static final float KEY_SHADOW_DISTANCE = 1f/48;
public static final int KEY_SHADOW_ALPHA = 61;
public static final int AMBIENT_SHADOW_ALPHA = 30;
private static final Object LOCK = new Object();
// Singleton object guarded by {#link #LOCK}
private static ShadowGenerator sShadowGenerator;
private int mIconSize;
private final Canvas mCanvas;
private final Paint mBlurPaint;
private final Paint mDrawPaint;
private final Context mContext;
private ShadowGenerator(Context context) {
mContext = context;
mIconSize = Utils.convertDpToPixel(context,63);
mCanvas = new Canvas();
mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
mBlurPaint.setMaskFilter(new BlurMaskFilter(mIconSize * BLUR_FACTOR, Blur.NORMAL));
mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
}
public synchronized Bitmap recreateIcon(Bitmap icon) {
mIconSize = Utils.convertDpToPixel(mContext,3)+icon.getWidth();
int[] offset = new int[2];
Bitmap shadow = icon.extractAlpha(mBlurPaint, offset);
Bitmap result = Bitmap.createBitmap(mIconSize, mIconSize, Config.ARGB_8888);
mCanvas.setBitmap(result);
// Draw ambient shadow
mDrawPaint.setAlpha(AMBIENT_SHADOW_ALPHA);
mCanvas.drawBitmap(shadow, offset[0], offset[1], mDrawPaint);
// Draw key shadow
mDrawPaint.setAlpha(KEY_SHADOW_ALPHA);
mCanvas.drawBitmap(shadow, offset[0], offset[1] + KEY_SHADOW_DISTANCE * mIconSize, mDrawPaint);
// Draw the icon
mDrawPaint.setAlpha(255);
mCanvas.drawBitmap(icon, 0, 0, mDrawPaint);
mCanvas.setBitmap(null);
return result;
}
public static ShadowGenerator getInstance(Context context) {
synchronized (LOCK) {
if (sShadowGenerator == null) {
sShadowGenerator = new ShadowGenerator(context);
}
}
return sShadowGenerator;
}
}
If you want to use the custom imageView, I suggest you use this one
View look perfect and dont't use any nine path image

Categories

Resources