Обычай ImageView с тенью
хорошо, я читал и искал вокруг, и теперь бьюсь головой о стену, пытаясь понять это. Вот что у меня есть до сих пор:
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, когда Я запускаю программу.
какие мысли? Спасибо.
EDIT: поэтому я поговорил с RomainGuy в IRC-канале, и теперь он работает для простых прямоугольных изображений с приведенным ниже кодом. Он по-прежнему не будет рисовать тень непосредственно на прозрачность моего растрового изображения, поэтому я все еще работаю над этим.
@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);
}
10 ответов:
хорошо, я не предвижу больше ответов на этот вопрос, поэтому то, что я в конечном итоге собираюсь сейчас, - это просто решение для прямоугольных изображений. Я использовал следующий 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, pdf найдено здесь.
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);надеюсь, что это помогает.
Примечания
Я верю этому ответу от 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>
мое грязное решение:
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; } ... }
здесь реализация Пол Берк 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: выполнить
setLayerType(LAYER_TYPE_SOFTWARE, mShadow);только если уровень API > 10
Я построил на ответ выше -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, как вы считаете нужным.
используйте этот класс для рисования теней на растровых изображениях
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; } }



Comments