summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2015-03-23 16:33:32 -0700
committerAdam Powell <adamp@google.com>2015-03-24 16:19:20 -0700
commit2b25e2eee032a23fd20a136d5a747098f8b6452f (patch)
treeebd81a4f89a8a550ab8b4de58ea09e5cd0da7911 /core/java/android
parent4d24b14d129871692b4c844d71e0179d0403e3a4 (diff)
downloadframeworks_base-2b25e2eee032a23fd20a136d5a747098f8b6452f.zip
frameworks_base-2b25e2eee032a23fd20a136d5a747098f8b6452f.tar.gz
frameworks_base-2b25e2eee032a23fd20a136d5a747098f8b6452f.tar.bz2
Move foreground drawable down from FrameLayout into View
This will allow any View to include foreground drawables. This is useful for cases where a foreground drawable is a more appropriate place to put a state list to show focus or touch highlighting. Also add View#onDrawForeground as a public API hook for drawing decorations after primary view content and child views such as scrollbars, foreground drawables and EdgeEffects. Change-Id: If1e4700af69db6876970f8f4ad5e3eab11b8034c
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/view/View.java339
-rw-r--r--core/java/android/widget/FrameLayout.java326
2 files changed, 339 insertions, 326 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f5de8e3..c29b5c9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3168,6 +3168,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private Drawable mBackground;
private TintInfo mBackgroundTint;
+ @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
+ private ForegroundInfo mForegroundInfo;
+
/**
* RenderNode used for backgrounds.
* <p>
@@ -3182,13 +3185,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private String mTransitionName;
- private static class TintInfo {
+ static class TintInfo {
ColorStateList mTintList;
PorterDuff.Mode mTintMode;
boolean mHasTintMode;
boolean mHasTintList;
}
+ private static class ForegroundInfo {
+ private Drawable mDrawable;
+ private TintInfo mTintInfo;
+ private int mGravity = Gravity.START | Gravity.TOP;
+ private boolean mInsidePadding = true;
+ private boolean mBoundsChanged;
+ private final Rect mSelfBounds = new Rect();
+ private final Rect mOverlayBounds = new Rect();
+ }
+
static class ListenerInfo {
/**
* Listener used to dispatch focus change events.
@@ -4056,6 +4069,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
PROVIDER_BACKGROUND));
break;
+ case R.styleable.View_foreground:
+ setForeground(a.getDrawable(attr));
+ break;
+ case R.styleable.View_foregroundGravity:
+ setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
+ break;
+ case R.styleable.View_foregroundTintMode:
+ setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
+ break;
+ case R.styleable.View_foregroundTint:
+ setForegroundTintList(a.getColorStateList(attr));
+ break;
+ case R.styleable.View_foregroundInsidePadding:
+ if (mForegroundInfo == null) {
+ mForegroundInfo = new ForegroundInfo();
+ }
+ mForegroundInfo.mInsidePadding = a.getBoolean(attr,
+ mForegroundInfo.mInsidePadding);
+ break;
}
}
@@ -8801,6 +8833,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (dr != null && visible != dr.isVisible()) {
dr.setVisible(visible, false);
}
+ final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+ if (fg != null && visible != fg.isVisible()) {
+ fg.setVisible(visible, false);
+ }
}
/**
@@ -9917,6 +9953,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
mBackgroundSizeChanged = true;
+ if (mForegroundInfo != null) {
+ mForegroundInfo.mBoundsChanged = true;
+ }
final AttachInfo ai = mAttachInfo;
if (ai != null) {
@@ -10755,6 +10794,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
invalidate(true);
}
mBackgroundSizeChanged = true;
+ if (mForegroundInfo != null) {
+ mForegroundInfo.mBoundsChanged = true;
+ }
invalidateParentIfNeeded();
if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
@@ -10820,6 +10862,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
invalidate(true);
}
mBackgroundSizeChanged = true;
+ if (mForegroundInfo != null) {
+ mForegroundInfo.mBoundsChanged = true;
+ }
invalidateParentIfNeeded();
if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
@@ -10879,6 +10924,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
invalidate(true);
}
mBackgroundSizeChanged = true;
+ if (mForegroundInfo != null) {
+ mForegroundInfo.mBoundsChanged = true;
+ }
invalidateParentIfNeeded();
if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
@@ -10935,6 +10983,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
invalidate(true);
}
mBackgroundSizeChanged = true;
+ if (mForegroundInfo != null) {
+ mForegroundInfo.mBoundsChanged = true;
+ }
invalidateParentIfNeeded();
if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
// View was rejected last time it was drawn by its parent; this may have changed
@@ -15313,13 +15364,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Step 4, draw the children
dispatchDraw(canvas);
- // Step 6, draw decorations (scrollbars)
- onDrawScrollBars(canvas);
-
+ // Overlay is part of the content and draws beneath Foreground
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
+ // Step 6, draw decorations (foreground, scrollbars)
+ onDrawForeground(canvas);
+
// we're done...
return;
}
@@ -15461,12 +15513,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
canvas.restoreToCount(saveCount);
- // Step 6, draw decorations (scrollbars)
- onDrawScrollBars(canvas);
-
+ // Overlay is part of the content and draws beneath Foreground
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
+
+ // Step 6, draw decorations (foreground, scrollbars)
+ onDrawForeground(canvas);
}
/**
@@ -15849,6 +15902,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags |= drawn;
mBackgroundSizeChanged = true;
+ if (mForegroundInfo != null) {
+ mForegroundInfo.mBoundsChanged = true;
+ }
notifySubtreeAccessibilityStateChangedIfNeeded();
}
@@ -15992,6 +16048,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mBackground != null) {
mBackground.setLayoutDirection(layoutDirection);
}
+ if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
+ mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
+ }
mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
onResolveDrawables(layoutDirection);
}
@@ -16047,7 +16106,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@CallSuper
protected boolean verifyDrawable(Drawable who) {
- return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who);
+ return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
+ || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
}
/**
@@ -16065,9 +16125,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
protected void drawableStateChanged() {
final int[] state = getDrawableState();
- final Drawable d = mBackground;
- if (d != null && d.isStateful()) {
- d.setState(state);
+ final Drawable bg = mBackground;
+ if (bg != null && bg.isStateful()) {
+ bg.setState(state);
+ }
+
+ final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+ if (fg != null && fg.isStateful()) {
+ fg.setState(state);
}
if (mScrollCache != null) {
@@ -16099,6 +16164,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mBackground != null) {
mBackground.setHotspot(x, y);
}
+ if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
+ mForegroundInfo.mDrawable.setHotspot(x, y);
+ }
dispatchDrawableHotspotChanged(x, y);
}
@@ -16270,6 +16338,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mStateListAnimator != null) {
mStateListAnimator.jumpToCurrentState();
}
+ if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
+ mForegroundInfo.mDrawable.jumpToCurrentState();
+ }
}
/**
@@ -16554,6 +16625,248 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Returns the drawable used as the foreground of this View. The
+ * foreground drawable, if non-null, is always drawn on top of the view's content.
+ *
+ * @return a Drawable or null if no foreground was set
+ *
+ * @see #onDrawForeground(Canvas)
+ */
+ public Drawable getForeground() {
+ return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+ }
+
+ /**
+ * Supply a Drawable that is to be rendered on top of all of the content in the view.
+ *
+ * @param foreground the Drawable to be drawn on top of the children
+ *
+ * @attr ref android.R.styleable#View_foreground
+ */
+ public void setForeground(Drawable foreground) {
+ if (mForegroundInfo == null) {
+ if (foreground == null) {
+ // Nothing to do.
+ return;
+ }
+ mForegroundInfo = new ForegroundInfo();
+ }
+
+ if (foreground == mForegroundInfo.mDrawable) {
+ // Nothing to do
+ return;
+ }
+
+ if (mForegroundInfo.mDrawable != null) {
+ mForegroundInfo.mDrawable.setCallback(null);
+ unscheduleDrawable(mForegroundInfo.mDrawable);
+ }
+
+ mForegroundInfo.mDrawable = foreground;
+ if (foreground != null) {
+ setWillNotDraw(false);
+ foreground.setCallback(this);
+ foreground.setLayoutDirection(getLayoutDirection());
+ if (foreground.isStateful()) {
+ foreground.setState(getDrawableState());
+ }
+ applyForegroundTint();
+ }
+ requestLayout();
+ invalidate();
+ }
+
+ /**
+ * Magic bit used to support features of framework-internal window decor implementation details.
+ * This used to live exclusively in FrameLayout.
+ *
+ * @return true if the foreground should draw inside the padding region or false
+ * if it should draw inset by the view's padding
+ * @hide internal use only; only used by FrameLayout and internal screen layouts.
+ */
+ public boolean isForegroundInsidePadding() {
+ return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
+ }
+
+ /**
+ * Describes how the foreground is positioned.
+ *
+ * @return foreground gravity.
+ *
+ * @see #setForegroundGravity(int)
+ *
+ * @attr ref android.R.styleable#View_foregroundGravity
+ */
+ public int getForegroundGravity() {
+ return mForegroundInfo != null ? mForegroundInfo.mGravity
+ : Gravity.START | Gravity.TOP;
+ }
+
+ /**
+ * Describes how the foreground is positioned. Defaults to START and TOP.
+ *
+ * @param gravity see {@link android.view.Gravity}
+ *
+ * @see #getForegroundGravity()
+ *
+ * @attr ref android.R.styleable#View_foregroundGravity
+ */
+ public void setForegroundGravity(int gravity) {
+ if (mForegroundInfo == null) {
+ mForegroundInfo = new ForegroundInfo();
+ }
+
+ if (mForegroundInfo.mGravity != gravity) {
+ if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
+ gravity |= Gravity.START;
+ }
+
+ if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
+ gravity |= Gravity.TOP;
+ }
+
+ mForegroundInfo.mGravity = gravity;
+ requestLayout();
+ }
+ }
+
+ /**
+ * Applies a tint to the foreground drawable. Does not modify the current tint
+ * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+ * <p>
+ * Subsequent calls to {@link #setForeground(Drawable)} will automatically
+ * mutate the drawable and apply the specified tint and tint mode using
+ * {@link Drawable#setTintList(ColorStateList)}.
+ *
+ * @param tint the tint to apply, may be {@code null} to clear tint
+ *
+ * @attr ref android.R.styleable#View_foregroundTint
+ * @see #getForegroundTintList()
+ * @see Drawable#setTintList(ColorStateList)
+ */
+ public void setForegroundTintList(@Nullable ColorStateList tint) {
+ if (mForegroundInfo == null) {
+ mForegroundInfo = new ForegroundInfo();
+ }
+ if (mForegroundInfo.mTintInfo == null) {
+ mForegroundInfo.mTintInfo = new TintInfo();
+ }
+ mForegroundInfo.mTintInfo.mTintList = tint;
+ mForegroundInfo.mTintInfo.mHasTintList = true;
+
+ applyForegroundTint();
+ }
+
+ /**
+ * Return the tint applied to the foreground drawable, if specified.
+ *
+ * @return the tint applied to the foreground drawable
+ * @attr ref android.R.styleable#View_foregroundTint
+ * @see #setForegroundTintList(ColorStateList)
+ */
+ @Nullable
+ public ColorStateList getForegroundTintList() {
+ return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
+ ? mBackgroundTint.mTintList : null;
+ }
+
+ /**
+ * Specifies the blending mode used to apply the tint specified by
+ * {@link #setForegroundTintList(ColorStateList)}} to the background
+ * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
+ *
+ * @param tintMode the blending mode used to apply the tint, may be
+ * {@code null} to clear tint
+ * @attr ref android.R.styleable#View_foregroundTintMode
+ * @see #getForegroundTintMode()
+ * @see Drawable#setTintMode(PorterDuff.Mode)
+ */
+ public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
+ if (mBackgroundTint == null) {
+ mBackgroundTint = new TintInfo();
+ }
+ mBackgroundTint.mTintMode = tintMode;
+ mBackgroundTint.mHasTintMode = true;
+
+ applyBackgroundTint();
+ }
+
+ /**
+ * Return the blending mode used to apply the tint to the foreground
+ * drawable, if specified.
+ *
+ * @return the blending mode used to apply the tint to the foreground
+ * drawable
+ * @attr ref android.R.styleable#View_foregroundTintMode
+ * @see #setBackgroundTintMode(PorterDuff.Mode)
+ */
+ @Nullable
+ public PorterDuff.Mode getForegroundTintMode() {
+ return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
+ ? mForegroundInfo.mTintInfo.mTintMode : null;
+ }
+
+ private void applyForegroundTint() {
+ if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
+ && mForegroundInfo.mTintInfo != null) {
+ final TintInfo tintInfo = mForegroundInfo.mTintInfo;
+ if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
+ mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
+
+ if (tintInfo.mHasTintList) {
+ mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
+ }
+
+ if (tintInfo.mHasTintMode) {
+ mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
+ }
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mForegroundInfo.mDrawable.isStateful()) {
+ mForegroundInfo.mDrawable.setState(getDrawableState());
+ }
+ }
+ }
+ }
+
+ /**
+ * Draw any foreground content for this view.
+ *
+ * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
+ * drawable or other view-specific decorations. The foreground is drawn on top of the
+ * primary view content.</p>
+ *
+ * @param canvas canvas to draw into
+ */
+ public void onDrawForeground(Canvas canvas) {
+ onDrawScrollBars(canvas);
+
+ final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+ if (foreground != null) {
+ if (mForegroundInfo.mBoundsChanged) {
+ mForegroundInfo.mBoundsChanged = false;
+ final Rect selfBounds = mForegroundInfo.mSelfBounds;
+ final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
+
+ if (mForegroundInfo.mInsidePadding) {
+ selfBounds.set(0, 0, getWidth(), getHeight());
+ } else {
+ selfBounds.set(getPaddingLeft(), getPaddingTop(),
+ getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
+ }
+
+ final int ld = getLayoutDirection();
+ Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
+ foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
+ foreground.setBounds(overlayBounds);
+ }
+
+ foreground.draw(canvas);
+ }
+ }
+
+ /**
* Sets the padding. The view may add on the space required to display
* the scrollbars, depending on the style and visibility of the scrollbars.
* So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
@@ -18090,6 +18403,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// parts from this transparent region.
applyDrawableToTransparentRegion(mBackground, region);
}
+ final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+ if (foreground != null) {
+ applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
+ }
}
return true;
}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index f6d198b..0602944 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -53,8 +53,6 @@ import com.android.internal.R;
* only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()}
* is set to true.
*
- * @attr ref android.R.styleable#FrameLayout_foreground
- * @attr ref android.R.styleable#FrameLayout_foregroundGravity
* @attr ref android.R.styleable#FrameLayout_measureAllChildren
*/
@RemoteView
@@ -64,13 +62,6 @@ public class FrameLayout extends ViewGroup {
@ViewDebug.ExportedProperty(category = "measurement")
boolean mMeasureAllChildren = false;
- @ViewDebug.ExportedProperty(category = "drawing")
- private Drawable mForeground;
- private ColorStateList mForegroundTintList = null;
- private PorterDuff.Mode mForegroundTintMode = null;
- private boolean mHasForegroundTint = false;
- private boolean mHasForegroundTintMode = false;
-
@ViewDebug.ExportedProperty(category = "padding")
private int mForegroundPaddingLeft = 0;
@@ -85,15 +76,6 @@ public class FrameLayout extends ViewGroup {
private final Rect mSelfBounds = new Rect();
private final Rect mOverlayBounds = new Rect();
-
- @ViewDebug.ExportedProperty(category = "drawing")
- private int mForegroundGravity = Gravity.FILL;
-
- /** {@hide} */
- @ViewDebug.ExportedProperty(category = "drawing")
- protected boolean mForegroundInPadding = true;
-
- boolean mForegroundBoundsChanged = false;
private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1);
@@ -115,48 +97,12 @@ public class FrameLayout extends ViewGroup {
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.FrameLayout, defStyleAttr, defStyleRes);
-
- mForegroundGravity = a.getInt(
- com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity);
-
- final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
- if (d != null) {
- setForeground(d);
- }
if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
setMeasureAllChildren(true);
}
- if (a.hasValue(R.styleable.FrameLayout_foregroundTintMode)) {
- mForegroundTintMode = Drawable.parseTintMode(a.getInt(
- R.styleable.FrameLayout_foregroundTintMode, -1), mForegroundTintMode);
- mHasForegroundTintMode = true;
- }
-
- if (a.hasValue(R.styleable.FrameLayout_foregroundTint)) {
- mForegroundTintList = a.getColorStateList(R.styleable.FrameLayout_foregroundTint);
- mHasForegroundTint = true;
- }
-
- mForegroundInPadding = a.getBoolean(R.styleable.FrameLayout_foregroundInsidePadding, true);
-
a.recycle();
-
- applyForegroundTint();
- }
-
- /**
- * Describes how the foreground is positioned.
- *
- * @return foreground gravity.
- *
- * @see #setForegroundGravity(int)
- *
- * @attr ref android.R.styleable#FrameLayout_foregroundGravity
- */
- public int getForegroundGravity() {
- return mForegroundGravity;
}
/**
@@ -166,25 +112,18 @@ public class FrameLayout extends ViewGroup {
*
* @see #getForegroundGravity()
*
- * @attr ref android.R.styleable#FrameLayout_foregroundGravity
+ * @attr ref android.R.styleable#View_foregroundGravity
*/
@android.view.RemotableViewMethod
public void setForegroundGravity(int foregroundGravity) {
- if (mForegroundGravity != foregroundGravity) {
- if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
- foregroundGravity |= Gravity.START;
- }
-
- if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
- foregroundGravity |= Gravity.TOP;
- }
-
- mForegroundGravity = foregroundGravity;
-
+ if (getForegroundGravity() != foregroundGravity) {
+ super.setForegroundGravity(foregroundGravity);
- if (mForegroundGravity == Gravity.FILL && mForeground != null) {
+ // calling get* again here because the set above may apply default constraints
+ final Drawable foreground = getForeground();
+ if (getForegroundGravity() == Gravity.FILL && foreground != null) {
Rect padding = new Rect();
- if (mForeground.getPadding(padding)) {
+ if (foreground.getPadding(padding)) {
mForegroundPaddingLeft = padding.left;
mForegroundPaddingTop = padding.top;
mForegroundPaddingRight = padding.right;
@@ -201,53 +140,6 @@ public class FrameLayout extends ViewGroup {
}
}
- @Override
- protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
- super.onVisibilityChanged(changedView, visibility);
-
- final Drawable dr = mForeground;
- if (dr != null) {
- final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
- if (visible != dr.isVisible()) {
- dr.setVisible(visible, false);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return super.verifyDrawable(who) || (who == mForeground);
- }
-
- @Override
- public void jumpDrawablesToCurrentState() {
- super.jumpDrawablesToCurrentState();
- if (mForeground != null) mForeground.jumpToCurrentState();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- if (mForeground != null && mForeground.isStateful()) {
- mForeground.setState(getDrawableState());
- }
- }
-
- @Override
- public void drawableHotspotChanged(float x, float y) {
- super.drawableHotspotChanged(x, y);
-
- if (mForeground != null) {
- mForeground.setHotspot(x, y);
- }
- }
-
/**
* Returns a set of layout parameters with a width of
* {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT},
@@ -258,161 +150,23 @@ public class FrameLayout extends ViewGroup {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
- /**
- * Supply a Drawable that is to be rendered on top of all of the child
- * views in the frame layout. Any padding in the Drawable will be taken
- * into account by ensuring that the children are inset to be placed
- * inside of the padding area.
- *
- * @param d The Drawable to be drawn on top of the children.
- *
- * @attr ref android.R.styleable#FrameLayout_foreground
- */
- public void setForeground(Drawable d) {
- if (mForeground != d) {
- if (mForeground != null) {
- mForeground.setCallback(null);
- unscheduleDrawable(mForeground);
- }
-
- mForeground = d;
- mForegroundPaddingLeft = 0;
- mForegroundPaddingTop = 0;
- mForegroundPaddingRight = 0;
- mForegroundPaddingBottom = 0;
-
- if (d != null) {
- setWillNotDraw(false);
- d.setCallback(this);
- d.setLayoutDirection(getLayoutDirection());
- if (d.isStateful()) {
- d.setState(getDrawableState());
- }
- applyForegroundTint();
- if (mForegroundGravity == Gravity.FILL) {
- Rect padding = new Rect();
- if (d.getPadding(padding)) {
- mForegroundPaddingLeft = padding.left;
- mForegroundPaddingTop = padding.top;
- mForegroundPaddingRight = padding.right;
- mForegroundPaddingBottom = padding.bottom;
- }
- }
- } else {
- setWillNotDraw(true);
- }
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Returns the drawable used as the foreground of this FrameLayout. The
- * foreground drawable, if non-null, is always drawn on top of the children.
- *
- * @return A Drawable or null if no foreground was set.
- */
- public Drawable getForeground() {
- return mForeground;
- }
-
- /**
- * Applies a tint to the foreground drawable. Does not modify the current
- * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
- * <p>
- * Subsequent calls to {@link #setForeground(Drawable)} will automatically
- * mutate the drawable and apply the specified tint and tint mode using
- * {@link Drawable#setTintList(ColorStateList)}.
- *
- * @param tint the tint to apply, may be {@code null} to clear tint
- *
- * @attr ref android.R.styleable#FrameLayout_foregroundTint
- * @see #getForegroundTintList()
- * @see Drawable#setTintList(ColorStateList)
- */
- public void setForegroundTintList(@Nullable ColorStateList tint) {
- mForegroundTintList = tint;
- mHasForegroundTint = true;
-
- applyForegroundTint();
- }
-
- /**
- * @return the tint applied to the foreground drawable
- * @attr ref android.R.styleable#FrameLayout_foregroundTint
- * @see #setForegroundTintList(ColorStateList)
- */
- @Nullable
- public ColorStateList getForegroundTintList() {
- return mForegroundTintList;
- }
-
- /**
- * Specifies the blending mode used to apply the tint specified by
- * {@link #setForegroundTintList(ColorStateList)}} to the foreground drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be
- * {@code null} to clear tint
- * @attr ref android.R.styleable#FrameLayout_foregroundTintMode
- * @see #getForegroundTintMode()
- * @see Drawable#setTintMode(PorterDuff.Mode)
- */
- public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
- mForegroundTintMode = tintMode;
- mHasForegroundTintMode = true;
-
- applyForegroundTint();
- }
-
- /**
- * @return the blending mode used to apply the tint to the foreground
- * drawable
- * @attr ref android.R.styleable#FrameLayout_foregroundTintMode
- * @see #setForegroundTintMode(PorterDuff.Mode)
- */
- @Nullable
- public PorterDuff.Mode getForegroundTintMode() {
- return mForegroundTintMode;
- }
-
- private void applyForegroundTint() {
- if (mForeground != null && (mHasForegroundTint || mHasForegroundTintMode)) {
- mForeground = mForeground.mutate();
-
- if (mHasForegroundTint) {
- mForeground.setTintList(mForegroundTintList);
- }
-
- if (mHasForegroundTintMode) {
- mForeground.setTintMode(mForegroundTintMode);
- }
-
- // The drawable (or one of its children) may not have been
- // stateful before applying the tint, so let's try again.
- if (mForeground.isStateful()) {
- mForeground.setState(getDrawableState());
- }
- }
- }
-
int getPaddingLeftWithForeground() {
- return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
+ return isForegroundInsidePadding() ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
mPaddingLeft + mForegroundPaddingLeft;
}
int getPaddingRightWithForeground() {
- return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) :
+ return isForegroundInsidePadding() ? Math.max(mPaddingRight, mForegroundPaddingRight) :
mPaddingRight + mForegroundPaddingRight;
}
private int getPaddingTopWithForeground() {
- return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) :
+ return isForegroundInsidePadding() ? Math.max(mPaddingTop, mForegroundPaddingTop) :
mPaddingTop + mForegroundPaddingTop;
}
private int getPaddingBottomWithForeground() {
- return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
+ return isForegroundInsidePadding() ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
mPaddingBottom + mForegroundPaddingBottom;
}
@@ -527,8 +281,6 @@ public class FrameLayout extends ViewGroup {
final int parentTop = getPaddingTopWithForeground();
final int parentBottom = bottom - top - getPaddingBottomWithForeground();
- mForegroundBoundsChanged = true;
-
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
@@ -585,62 +337,6 @@ public class FrameLayout extends ViewGroup {
}
/**
- * {@inheritDoc}
- */
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mForegroundBoundsChanged = true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
-
- if (mForeground != null) {
- final Drawable foreground = mForeground;
-
- if (mForegroundBoundsChanged) {
- mForegroundBoundsChanged = false;
- final Rect selfBounds = mSelfBounds;
- final Rect overlayBounds = mOverlayBounds;
-
- final int w = mRight-mLeft;
- final int h = mBottom-mTop;
-
- if (mForegroundInPadding) {
- selfBounds.set(0, 0, w, h);
- } else {
- selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
- }
-
- final int layoutDirection = getLayoutDirection();
- Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
- foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
- layoutDirection);
- foreground.setBounds(overlayBounds);
- }
-
- foreground.draw(canvas);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean gatherTransparentRegion(Region region) {
- boolean opaque = super.gatherTransparentRegion(region);
- if (region != null && mForeground != null) {
- applyDrawableToTransparentRegion(mForeground, region);
- }
- return opaque;
- }
-
- /**
* Sets whether to consider all children, or just those in
* the VISIBLE or INVISIBLE state, when measuring. Defaults to false.
*