package com.novoda.viewtils; import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; import android.widget.RelativeLayout; public class RelativeLayoutWithForeground extends RelativeLayout { private static final int INVALID_FOREGROUND_ID = 0; private Drawable foreground; public RelativeLayoutWithForeground(Context context, AttributeSet attrs) { super(context, attrs); applyForeground(context, attrs); } public RelativeLayoutWithForeground(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); applyForeground(context, attrs); } private void applyForeground(Context context, AttributeSet attrs) { TypedArray xml = context.obtainStyledAttributes(attrs, R.styleable.RelativeLayoutWithForeground); int foregroundResId = INVALID_FOREGROUND_ID; try { foregroundResId = xml.getResourceId(R.styleable.RelativeLayoutWithForeground_foreground, INVALID_FOREGROUND_ID); } finally { xml.recycle(); } if (foregroundResId == INVALID_FOREGROUND_ID) { return; } Drawable drawable = getDrawable(getResources(), foregroundResId); setForeground(drawable); } @SuppressWarnings("deprecation") // getDrawable(int) deprecated since API 21, but the replacement is not available til then..! @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) private static Drawable getDrawable(Resources resources, int foregroundResId) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return resources.getDrawable(foregroundResId); } else { return resources.getDrawable(foregroundResId, null); } } public Drawable getForeground() { return foreground; } public void setForeground(Drawable foreground) { if (this.foreground == foreground) { return; } removeOldForegroundIfAny(); updateForeground(foreground); } private void updateForeground(Drawable foreground) { this.foreground = foreground; if (foreground == null) { setWillNotDraw(true); } else { setWillNotDraw(false); foreground.setCallback(this); if (foreground.isStateful()) { foreground.setState(getDrawableState()); } } requestLayout(); invalidate(); } private void removeOldForegroundIfAny() { if (foreground != null) { foreground.setCallback(null); unscheduleDrawable(foreground); } } @SuppressWarnings("PMD.CompareObjectsWithEquals") // Matching super implementation @Override protected boolean verifyDrawable(Drawable who) { return super.verifyDrawable(who) || (who == foreground); } @Override public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (foreground != null) { foreground.jumpToCurrentState(); } } @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (foreground != null && foreground.isStateful()) { foreground.setState(getDrawableState()); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (foreground != null) { foreground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); } } @Override public void draw(Canvas canvas) { super.draw(canvas); if (foreground != null) { foreground.draw(canvas); } } }