Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom ImageView with drop shadow

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);        } 
like image 440
Kevin Coppock Avatar asked Sep 12 '10 00:09

Kevin Coppock


People also ask

How to create shadow in ImageView in Android?

Basically, it works like a stack where each view is stacked on top of the other. Create a drawable file for shadow view and assign the name image_shadow and add the below code in this file. Now, open the XML file and add the below code into it, and set this drawable file as view background. That's it.

How to give elevation to layout in Android?

To set the default (resting) elevation of a view, use the android:elevation attribute in the XML layout. To set the elevation of a view in the code of an activity, use the View. setElevation() method.

What is elevation in Android XML?

Elevation (Android) Elevation is the relative depth, or distance, between two surfaces along the z-axis. Specifications: Elevation is measured in the same units as the x and y axes, typically in density-independent pixels (dp).


2 Answers

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:

alt text

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:

alt text

Not ideal, but it'll do.

like image 55
Kevin Coppock Avatar answered Oct 25 '22 16:10

Kevin Coppock


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); 

Hope this helps.

NOTES

  1. 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)
  2. SetShadowLayer does not work with hardware acceleration unfortunately so it greatly reduces performances (@Matt Wear) [1] [2]
like image 40
Paul Burke Avatar answered Oct 25 '22 18:10

Paul Burke