さて、私は周りを読んで探していましたが、今これを理解しようとして頭を壁にぶつけています。ここに私が持っているものがあります:
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);
}
}
測定値の「+5」は一時的なものです。私が理解したことから、ドロップシャドウがキャンバスに追加するサイズを決定するために、いくつかの計算を行う必要がありますよね?
しかし、私がこれを使用する場合:
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;
}
imageViewでは、プログラムを実行すると通常のImageViewだけが表示されます。
何かご意見は?ありがとう。
編集:だから私はIRCチャンネルでRomainGuyと話をし、以下のコードで普通の長方形の画像で動作するようにしました。それでも、ビットマップの透明度に直接影が描画されることはありませんので、私はまだそれに取り組んでいます。
@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);
}
さて、これに関するこれ以上の答えは見当たらないので、私が今のところ行き着いたのは、長方形の画像の単なる解決策です。次のNinePatchを使用しました。
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"
/>
かなり良い結果を得るには:
理想的ではありませんが、実行できます。
これは、DevoxxでのRomain Guyのプレゼンテーションから取得されました。pdfが見つかりました 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);
お役に立てれば。
メモ
IFuel からのこの答えを信じています
<?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>
私の汚い解決策:
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;
}
結果:
はい、どうぞ。 ImageViewのソースをxmlで静的に設定するか、コードで動的に設定します。
影はここに白です。
<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>
このコードを使用して、グラデーション境界線を適用することができます。
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;
}
お役に立てれば !
これは私のために働く...
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;
} ... }
ここで Paul Burke sの回答の実装:
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:APIレベルが10を超える場合にのみsetLayerType(LAYER_TYPE_SOFTWARE, mShadow);
を実行します
このクラスを使用して、ビットマップに影を描画します
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;
}
}
私は上記の答えに基づいて構築しました- https://stackoverflow.com/a/11155031/2060486 -すべての側面の周りに影を作成します。
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;
}
必要に応じてconstの色を変更します。