rendered paste body/**
* Custom layout to display "full-screen" cover artwork with a
* reflection effect. This layout should contain only one view, which
* will be placed over the bottom refection.
*/
public class ReflectionLayout extends ViewGroup
{
private static final String TAG = "ReflectionLayout";
private Paint mReflect = new Paint(Paint.FILTER_BITMAP_FLAG);
private Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
private Bitmap mBitmap;
private Rect mImageDim = new Rect();
private Rect mReflectionClip = new Rect();
private Rect mReflectionDim = new Rect();
public ReflectionLayout(Context context)
{
super(context);
init();
}
public ReflectionLayout(Context context, AttributeSet attrs, Map inflateParams)
{
super(context, attrs, inflateParams);
init();
}
public ReflectionLayout(Context context, AttributeSet attrs, Map inflateParams, int defStyle)
{
super(context, attrs, inflateParams, defStyle);
init();
}
private void init()
{
// mReflect.setXfermode(new PorterDuff(PorterDuff.Mode.DST_OUT));
}
public void setImageURI(Uri uri)
{
try
{
mBitmap = BitmapFactory.decodeStream
(mContext.getContentResolver().openInputStream(uri));
}
catch (Exception e)
{
Log.d(TAG, "Unable to read content: " + uri);
}
// configureBounds();
}
public void setImageResource(int id)
{
mBitmap = BitmapFactory.decodeResource(getResources(), id);
// configureBounds();
}
private void configureBounds()
{
Log.d(TAG, "configureBounds()");
/* Not ready yet... */
if (getChildCount() == 0)
return;
int w = getMeasuredWidth();
int h = getMeasuredHeight();
if (w == 0 || h == 0)
{
Log.d(TAG, "...abort!");
return;
}
View v = getChildAt(0);
int vh = v.getMeasuredHeight();
int bw = mBitmap.getWidth();
int bh = mBitmap.getHeight();
/* TODO: Keep aspect ratio. */
assert bw == bh;
mImageDim.set(0, 0, w, h - vh);
float portion = (float)vh / (float)h;
Log.d(TAG, "bh="+ bh + ", portion=" + portion);
mReflectionClip.set(0, bh - (int)((float)bh * portion), bw, bh);
mReflectionDim.set(0, 0, w, vh);
LinearGradient shader =
new LinearGradient(0, 0, 0, 10, 0xffff0000, 0xff00ff00,
TileMode.MIRROR);
mReflect.setShader(shader);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
Log.d(TAG, "onLayout");
assert getChildCount() == 1;
configureBounds();
int selfw = getMeasuredWidth();
int selfh = getMeasuredHeight();
View v = getChildAt(0);
int vh = v.getMeasuredHeight();
Log.d(TAG, "selfw=" + selfw + ", selfh=" + selfh);
Log.d(TAG, "vh=" + vh);
v.layout(0, selfh - vh, selfw, selfh);
}
@Override
protected void onMeasure(int widthSpec, int heightSpec)
{
Log.d(TAG, "onMeasure...");
assert getChildCount() == 1;
View v = getChildAt(0);
v.measure
(getChildMeasureSpec(widthSpec, 0, v.getLayoutParams().width),
getChildMeasureSpec(heightSpec, 0, v.getLayoutParams().height));
/* XXX: Our layout doesn't play nice with any other usage than
* the one we have in playlist.xml :) */
assert View.MeasureSpec.getMode(widthSpec) == View.MeasureSpec.EXACTLY;
assert View.MeasureSpec.getMode(heightSpec) == View.MeasureSpec.EXACTLY;
setMeasuredDimension
(View.MeasureSpec.getSize(widthSpec),
View.MeasureSpec.getSize(heightSpec));
}
@Override
protected void dispatchDraw(Canvas canvas)
{
assert getChildCount() == 1;
Rect r = new Rect();
getDrawingRect(r);
Log.d(TAG, "r=" + r);
Log.d(TAG, "clip=" + mReflectionClip);
Log.d(TAG, "dim=" + mReflectionDim);
canvas.drawBitmap(mBitmap, null, mImageDim, mPaint);
canvas.save();
canvas.translate(0, mImageDim.height() + mReflectionDim.height());
canvas.scale(1.0f, -1.0f);
canvas.drawBitmap(mBitmap, mReflectionClip, mReflectionDim,
mReflect);
canvas.restore();
super.dispatchDraw(canvas);
}
}