ImageView personalizado con sombra paralela
Bien, he estado leyendo y buscando y ahora me golpeo la cabeza contra la pared tratando de resolver esto. Esto es lo que tengo hasta ahora:
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);
}
}
Los "+5" en las mediciones están ahí como temporales; Por lo que tengo entendido, tendré que hacer algunos cálculos para determinar el tamaño que la sombra paralela agrega al lienzo, ¿verdad?
Pero cuando uso esto:
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;
}
en mi ImageView, todavía obtengo un ImageView normal cuando ejecuto el programa.
¿Alguna idea? Gracias.
EDITAR: Hablé con RomainGuy en el canal IRC y ahora lo tengo funcionando para imágenes rectangulares simples con el siguiente código. Sin embargo, todavía no dibujará la sombra directamente en la transparencia de mi mapa de bits, así que todavía estoy trabajando en eso.
@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);
}
Bien, no preveo más respuestas sobre esto, así que terminé eligiendo por ahora es solo una solución para imágenes rectangulares. He usado el siguiente NinePatch:
junto con el relleno apropiado en 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"
/>
para obtener un resultado bastante bueno:
no es ideal, pero servirá.
Esto está tomado de la presentación de Romain Guy en Devoxx, el pdf se encuentra aquí .
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);
NOTAS
- ¡No olvides que para Honeycomb y superiores debes invocar
setLayerType(LAYER_TYPE_SOFTWARE, mShadow)
, de lo contrario no verás tu sombra! (@Dmitriy_Boichenko) SetShadowLayer
Desafortunadamente, no funciona con aceleración de hardware, por lo que reduce considerablemente el rendimiento (@Matt Wear) [1] [2]
Creo que esta respuesta de 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>
Mi solución sucia:
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;
}
resultado: