All pastes #981792 Raw Edit

Stuff

public text v1 · immutable
·published 2008-04-12 01:05 UTC
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);
	}
}