«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

올해는 머신러닝이다.

[팁]Custom ImageView with drop shadow 본문

Android/Tip&Tech

[팁]Custom ImageView with drop shadow

행복한 수지아빠 2011. 6. 1. 12:43

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);      
}
link|edit|flag

@kcoppock: "it working now for plain rectangular images" ... so it doesn't work for non-rectangular images, and then I assume it also doesn't work for 9patch-images, correct? Did you meanwhile get it to work? Cause this approach by Romain Guy doesn't work for me in my test yet. – Mathias Lin Feb 24 at 10:33
Hmm, interesting question. I would think you could probably take your View that's using the 9-patch, and wrap it in a FrameLayout, and give the FrameLayout the drop shadow 9-patch background. But yeah, it only works for rectangular images, because there's no way for a 9-patch to follow transparency contours. I unfortunately haven't found a better solution, however, I haven't really tried again since. – kcoppock Feb 24 at 14:21

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.

link|edit|flag
I will definitely try this later! Thanks for the PDF as well, looks like interesting stuff. Is this presentation video available online to watch? – kcoppock Sep 16 '10 at 4:29

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.

link|edit|flag

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>
link|edit|flag
Definitely not what I'm looking for. I'm wanting an actual rendered drop shadow that fades to transparent; that will just give me a white box behind my image. – kcoppock Sep 15 '10 at 13:52
1  
@kcoppock - there's no need to downvote this answer - it wasn't really that bad. – CaspNZ Feb 13 at 23:08