Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget;
     18 
     19 import java.util.ArrayList;
     20 
     21 import android.annotation.Nullable;
     22 import android.content.Context;
     23 import android.content.res.ColorStateList;
     24 import android.content.res.TypedArray;
     25 import android.graphics.Canvas;
     26 import android.graphics.PorterDuff;
     27 import android.graphics.Rect;
     28 import android.graphics.Region;
     29 import android.graphics.drawable.Drawable;
     30 import android.util.AttributeSet;
     31 import android.view.Gravity;
     32 import android.view.RemotableViewMethod;
     33 import android.view.View;
     34 import android.view.ViewDebug;
     35 import android.view.ViewGroup;
     36 import android.view.accessibility.AccessibilityEvent;
     37 import android.view.accessibility.AccessibilityNodeInfo;
     38 import android.widget.RemoteViews.RemoteView;
     39 
     40 import com.android.internal.R;
     41 
     42 
     43 /**
     44  * FrameLayout is designed to block out an area on the screen to display
     45  * a single item. Generally, FrameLayout should be used to hold a single child view, because it can
     46  * be difficult to organize child views in a way that's scalable to different screen sizes without
     47  * the children overlapping each other. You can, however, add multiple children to a FrameLayout
     48  * and control their position within the FrameLayout by assigning gravity to each child, using the
     49  * <a href="FrameLayout.LayoutParams.html#attr_android:layout_gravity">{@code
     50  * android:layout_gravity}</a> attribute.
     51  * <p>Child views are drawn in a stack, with the most recently added child on top.
     52  * The size of the FrameLayout is the size of its largest child (plus padding), visible
     53  * or not (if the FrameLayout's parent permits). Views that are {@link android.view.View#GONE} are
     54  * used for sizing
     55  * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()}
     56  * is set to true.
     57  *
     58  * @attr ref android.R.styleable#FrameLayout_foreground
     59  * @attr ref android.R.styleable#FrameLayout_foregroundGravity
     60  * @attr ref android.R.styleable#FrameLayout_measureAllChildren
     61  */
     62 @RemoteView
     63 public class FrameLayout extends ViewGroup {
     64     private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
     65 
     66     @ViewDebug.ExportedProperty(category = "measurement")
     67     boolean mMeasureAllChildren = false;
     68 
     69     @ViewDebug.ExportedProperty(category = "drawing")
     70     private Drawable mForeground;
     71     private ColorStateList mForegroundTintList = null;
     72     private PorterDuff.Mode mForegroundTintMode = null;
     73     private boolean mHasForegroundTint = false;
     74     private boolean mHasForegroundTintMode = false;
     75 
     76     @ViewDebug.ExportedProperty(category = "padding")
     77     private int mForegroundPaddingLeft = 0;
     78 
     79     @ViewDebug.ExportedProperty(category = "padding")
     80     private int mForegroundPaddingTop = 0;
     81 
     82     @ViewDebug.ExportedProperty(category = "padding")
     83     private int mForegroundPaddingRight = 0;
     84 
     85     @ViewDebug.ExportedProperty(category = "padding")
     86     private int mForegroundPaddingBottom = 0;
     87 
     88     private final Rect mSelfBounds = new Rect();
     89     private final Rect mOverlayBounds = new Rect();
     90 
     91     @ViewDebug.ExportedProperty(category = "drawing")
     92     private int mForegroundGravity = Gravity.FILL;
     93 
     94     /** {@hide} */
     95     @ViewDebug.ExportedProperty(category = "drawing")
     96     protected boolean mForegroundInPadding = true;
     97 
     98     boolean mForegroundBoundsChanged = false;
     99 
    100     private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1);
    101 
    102     public FrameLayout(Context context) {
    103         super(context);
    104     }
    105 
    106     public FrameLayout(Context context, AttributeSet attrs) {
    107         this(context, attrs, 0);
    108     }
    109 
    110     public FrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    111         this(context, attrs, defStyleAttr, 0);
    112     }
    113 
    114     public FrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    115         super(context, attrs, defStyleAttr, defStyleRes);
    116 
    117         final TypedArray a = context.obtainStyledAttributes(
    118                 attrs, com.android.internal.R.styleable.FrameLayout, defStyleAttr, defStyleRes);
    119 
    120         mForegroundGravity = a.getInt(
    121                 com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity);
    122 
    123         final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
    124         if (d != null) {
    125             setForeground(d);
    126         }
    127 
    128         if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
    129             setMeasureAllChildren(true);
    130         }
    131 
    132         if (a.hasValue(R.styleable.FrameLayout_foregroundTintMode)) {
    133             mForegroundTintMode = Drawable.parseTintMode(a.getInt(
    134                     R.styleable.FrameLayout_foregroundTintMode, -1), mForegroundTintMode);
    135             mHasForegroundTintMode = true;
    136         }
    137 
    138         if (a.hasValue(R.styleable.FrameLayout_foregroundTint)) {
    139             mForegroundTintList = a.getColorStateList(R.styleable.FrameLayout_foregroundTint);
    140             mHasForegroundTint = true;
    141         }
    142 
    143         mForegroundInPadding = a.getBoolean(R.styleable.FrameLayout_foregroundInsidePadding, true);
    144 
    145         a.recycle();
    146 
    147         applyForegroundTint();
    148     }
    149 
    150     /**
    151      * Describes how the foreground is positioned.
    152      *
    153      * @return foreground gravity.
    154      *
    155      * @see #setForegroundGravity(int)
    156      *
    157      * @attr ref android.R.styleable#FrameLayout_foregroundGravity
    158      */
    159     public int getForegroundGravity() {
    160         return mForegroundGravity;
    161     }
    162 
    163     /**
    164      * Describes how the foreground is positioned. Defaults to START and TOP.
    165      *
    166      * @param foregroundGravity See {@link android.view.Gravity}
    167      *
    168      * @see #getForegroundGravity()
    169      *
    170      * @attr ref android.R.styleable#FrameLayout_foregroundGravity
    171      */
    172     @android.view.RemotableViewMethod
    173     public void setForegroundGravity(int foregroundGravity) {
    174         if (mForegroundGravity != foregroundGravity) {
    175             if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
    176                 foregroundGravity |= Gravity.START;
    177             }
    178 
    179             if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
    180                 foregroundGravity |= Gravity.TOP;
    181             }
    182 
    183             mForegroundGravity = foregroundGravity;
    184 
    185 
    186             if (mForegroundGravity == Gravity.FILL && mForeground != null) {
    187                 Rect padding = new Rect();
    188                 if (mForeground.getPadding(padding)) {
    189                     mForegroundPaddingLeft = padding.left;
    190                     mForegroundPaddingTop = padding.top;
    191                     mForegroundPaddingRight = padding.right;
    192                     mForegroundPaddingBottom = padding.bottom;
    193                 }
    194             } else {
    195                 mForegroundPaddingLeft = 0;
    196                 mForegroundPaddingTop = 0;
    197                 mForegroundPaddingRight = 0;
    198                 mForegroundPaddingBottom = 0;
    199             }
    200 
    201             requestLayout();
    202         }
    203     }
    204 
    205     @Override
    206     @RemotableViewMethod
    207     public void setVisibility(@Visibility int visibility) {
    208         super.setVisibility(visibility);
    209         if (mForeground != null) {
    210             mForeground.setVisible(visibility == VISIBLE, false);
    211         }
    212     }
    213 
    214     /**
    215      * {@inheritDoc}
    216      */
    217     @Override
    218     protected boolean verifyDrawable(Drawable who) {
    219         return super.verifyDrawable(who) || (who == mForeground);
    220     }
    221 
    222     @Override
    223     public void jumpDrawablesToCurrentState() {
    224         super.jumpDrawablesToCurrentState();
    225         if (mForeground != null) mForeground.jumpToCurrentState();
    226     }
    227 
    228     /**
    229      * {@inheritDoc}
    230      */
    231     @Override
    232     protected void drawableStateChanged() {
    233         super.drawableStateChanged();
    234         if (mForeground != null && mForeground.isStateful()) {
    235             mForeground.setState(getDrawableState());
    236         }
    237     }
    238 
    239     @Override
    240     public void drawableHotspotChanged(float x, float y) {
    241         super.drawableHotspotChanged(x, y);
    242 
    243         if (mForeground != null) {
    244             mForeground.setHotspot(x, y);
    245         }
    246     }
    247 
    248     /**
    249      * Returns a set of layout parameters with a width of
    250      * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT},
    251      * and a height of {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}.
    252      */
    253     @Override
    254     protected LayoutParams generateDefaultLayoutParams() {
    255         return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    256     }
    257 
    258     /**
    259      * Supply a Drawable that is to be rendered on top of all of the child
    260      * views in the frame layout.  Any padding in the Drawable will be taken
    261      * into account by ensuring that the children are inset to be placed
    262      * inside of the padding area.
    263      *
    264      * @param d The Drawable to be drawn on top of the children.
    265      *
    266      * @attr ref android.R.styleable#FrameLayout_foreground
    267      */
    268     public void setForeground(Drawable d) {
    269         if (mForeground != d) {
    270             if (mForeground != null) {
    271                 mForeground.setCallback(null);
    272                 unscheduleDrawable(mForeground);
    273             }
    274 
    275             mForeground = d;
    276             mForegroundPaddingLeft = 0;
    277             mForegroundPaddingTop = 0;
    278             mForegroundPaddingRight = 0;
    279             mForegroundPaddingBottom = 0;
    280 
    281             if (d != null) {
    282                 setWillNotDraw(false);
    283                 d.setCallback(this);
    284                 d.setLayoutDirection(getLayoutDirection());
    285                 if (d.isStateful()) {
    286                     d.setState(getDrawableState());
    287                 }
    288                 applyForegroundTint();
    289                 if (mForegroundGravity == Gravity.FILL) {
    290                     Rect padding = new Rect();
    291                     if (d.getPadding(padding)) {
    292                         mForegroundPaddingLeft = padding.left;
    293                         mForegroundPaddingTop = padding.top;
    294                         mForegroundPaddingRight = padding.right;
    295                         mForegroundPaddingBottom = padding.bottom;
    296                     }
    297                 }
    298             }  else {
    299                 setWillNotDraw(true);
    300             }
    301             requestLayout();
    302             invalidate();
    303         }
    304     }
    305 
    306     /**
    307      * Returns the drawable used as the foreground of this FrameLayout. The
    308      * foreground drawable, if non-null, is always drawn on top of the children.
    309      *
    310      * @return A Drawable or null if no foreground was set.
    311      */
    312     public Drawable getForeground() {
    313         return mForeground;
    314     }
    315 
    316     /**
    317      * Applies a tint to the foreground drawable. Does not modify the current
    318      * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
    319      * <p>
    320      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
    321      * mutate the drawable and apply the specified tint and tint mode using
    322      * {@link Drawable#setTintList(ColorStateList)}.
    323      *
    324      * @param tint the tint to apply, may be {@code null} to clear tint
    325      *
    326      * @attr ref android.R.styleable#FrameLayout_foregroundTint
    327      * @see #getForegroundTintList()
    328      * @see Drawable#setTintList(ColorStateList)
    329      */
    330     public void setForegroundTintList(@Nullable ColorStateList tint) {
    331         mForegroundTintList = tint;
    332         mHasForegroundTint = true;
    333 
    334         applyForegroundTint();
    335     }
    336 
    337     /**
    338      * @return the tint applied to the foreground drawable
    339      * @attr ref android.R.styleable#FrameLayout_foregroundTint
    340      * @see #setForegroundTintList(ColorStateList)
    341      */
    342     @Nullable
    343     public ColorStateList getForegroundTintList() {
    344         return mForegroundTintList;
    345     }
    346 
    347     /**
    348      * Specifies the blending mode used to apply the tint specified by
    349      * {@link #setForegroundTintList(ColorStateList)}} to the foreground drawable.
    350      * The default mode is {@link PorterDuff.Mode#SRC_IN}.
    351      *
    352      * @param tintMode the blending mode used to apply the tint, may be
    353      *                 {@code null} to clear tint
    354      * @attr ref android.R.styleable#FrameLayout_foregroundTintMode
    355      * @see #getForegroundTintMode()
    356      * @see Drawable#setTintMode(PorterDuff.Mode)
    357      */
    358     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
    359         mForegroundTintMode = tintMode;
    360         mHasForegroundTintMode = true;
    361 
    362         applyForegroundTint();
    363     }
    364 
    365     /**
    366      * @return the blending mode used to apply the tint to the foreground
    367      *         drawable
    368      * @attr ref android.R.styleable#FrameLayout_foregroundTintMode
    369      * @see #setForegroundTintMode(PorterDuff.Mode)
    370      */
    371     @Nullable
    372     public PorterDuff.Mode getForegroundTintMode() {
    373         return mForegroundTintMode;
    374     }
    375 
    376     private void applyForegroundTint() {
    377         if (mForeground != null && (mHasForegroundTint || mHasForegroundTintMode)) {
    378             mForeground = mForeground.mutate();
    379 
    380             if (mHasForegroundTint) {
    381                 mForeground.setTintList(mForegroundTintList);
    382             }
    383 
    384             if (mHasForegroundTintMode) {
    385                 mForeground.setTintMode(mForegroundTintMode);
    386             }
    387 
    388             // The drawable (or one of its children) may not have been
    389             // stateful before applying the tint, so let's try again.
    390             if (mForeground.isStateful()) {
    391                 mForeground.setState(getDrawableState());
    392             }
    393         }
    394     }
    395 
    396     int getPaddingLeftWithForeground() {
    397         return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
    398             mPaddingLeft + mForegroundPaddingLeft;
    399     }
    400 
    401     int getPaddingRightWithForeground() {
    402         return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) :
    403             mPaddingRight + mForegroundPaddingRight;
    404     }
    405 
    406     private int getPaddingTopWithForeground() {
    407         return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) :
    408             mPaddingTop + mForegroundPaddingTop;
    409     }
    410 
    411     private int getPaddingBottomWithForeground() {
    412         return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
    413             mPaddingBottom + mForegroundPaddingBottom;
    414     }
    415 
    416 
    417     /**
    418      * {@inheritDoc}
    419      */
    420     @Override
    421     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    422         int count = getChildCount();
    423 
    424         final boolean measureMatchParentChildren =
    425                 MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
    426                 MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
    427         mMatchParentChildren.clear();
    428 
    429         int maxHeight = 0;
    430         int maxWidth = 0;
    431         int childState = 0;
    432 
    433         for (int i = 0; i < count; i++) {
    434             final View child = getChildAt(i);
    435             if (mMeasureAllChildren || child.getVisibility() != GONE) {
    436                 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
    437                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    438                 maxWidth = Math.max(maxWidth,
    439                         child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
    440                 maxHeight = Math.max(maxHeight,
    441                         child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
    442                 childState = combineMeasuredStates(childState, child.getMeasuredState());
    443                 if (measureMatchParentChildren) {
    444                     if (lp.width == LayoutParams.MATCH_PARENT ||
    445                             lp.height == LayoutParams.MATCH_PARENT) {
    446                         mMatchParentChildren.add(child);
    447                     }
    448                 }
    449             }
    450         }
    451 
    452         // Account for padding too
    453         maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground();
    454         maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground();
    455 
    456         // Check against our minimum height and width
    457         maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
    458         maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
    459 
    460         // Check against our foreground's minimum height and width
    461         final Drawable drawable = getForeground();
    462         if (drawable != null) {
    463             maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
    464             maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
    465         }
    466 
    467         setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
    468                 resolveSizeAndState(maxHeight, heightMeasureSpec,
    469                         childState << MEASURED_HEIGHT_STATE_SHIFT));
    470 
    471         count = mMatchParentChildren.size();
    472         if (count > 1) {
    473             for (int i = 0; i < count; i++) {
    474                 final View child = mMatchParentChildren.get(i);
    475 
    476                 final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    477                 int childWidthMeasureSpec;
    478                 int childHeightMeasureSpec;
    479 
    480                 if (lp.width == LayoutParams.MATCH_PARENT) {
    481                     childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() -
    482                             getPaddingLeftWithForeground() - getPaddingRightWithForeground() -
    483                             lp.leftMargin - lp.rightMargin,
    484                             MeasureSpec.EXACTLY);
    485                 } else {
    486                     childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
    487                             getPaddingLeftWithForeground() + getPaddingRightWithForeground() +
    488                             lp.leftMargin + lp.rightMargin,
    489                             lp.width);
    490                 }
    491 
    492                 if (lp.height == LayoutParams.MATCH_PARENT) {
    493                     childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() -
    494                             getPaddingTopWithForeground() - getPaddingBottomWithForeground() -
    495                             lp.topMargin - lp.bottomMargin,
    496                             MeasureSpec.EXACTLY);
    497                 } else {
    498                     childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
    499                             getPaddingTopWithForeground() + getPaddingBottomWithForeground() +
    500                             lp.topMargin + lp.bottomMargin,
    501                             lp.height);
    502                 }
    503 
    504                 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    505             }
    506         }
    507     }
    508 
    509     /**
    510      * {@inheritDoc}
    511      */
    512     @Override
    513     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    514         layoutChildren(left, top, right, bottom, false /* no force left gravity */);
    515     }
    516 
    517     void layoutChildren(int left, int top, int right, int bottom,
    518                                   boolean forceLeftGravity) {
    519         final int count = getChildCount();
    520 
    521         final int parentLeft = getPaddingLeftWithForeground();
    522         final int parentRight = right - left - getPaddingRightWithForeground();
    523 
    524         final int parentTop = getPaddingTopWithForeground();
    525         final int parentBottom = bottom - top - getPaddingBottomWithForeground();
    526 
    527         mForegroundBoundsChanged = true;
    528 
    529         for (int i = 0; i < count; i++) {
    530             final View child = getChildAt(i);
    531             if (child.getVisibility() != GONE) {
    532                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    533 
    534                 final int width = child.getMeasuredWidth();
    535                 final int height = child.getMeasuredHeight();
    536 
    537                 int childLeft;
    538                 int childTop;
    539 
    540                 int gravity = lp.gravity;
    541                 if (gravity == -1) {
    542                     gravity = DEFAULT_CHILD_GRAVITY;
    543                 }
    544 
    545                 final int layoutDirection = getLayoutDirection();
    546                 final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
    547                 final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
    548 
    549                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
    550                     case Gravity.CENTER_HORIZONTAL:
    551                         childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
    552                         lp.leftMargin - lp.rightMargin;
    553                         break;
    554                     case Gravity.RIGHT:
    555                         if (!forceLeftGravity) {
    556                             childLeft = parentRight - width - lp.rightMargin;
    557                             break;
    558                         }
    559                     case Gravity.LEFT:
    560                     default:
    561                         childLeft = parentLeft + lp.leftMargin;
    562                 }
    563 
    564                 switch (verticalGravity) {
    565                     case Gravity.TOP:
    566                         childTop = parentTop + lp.topMargin;
    567                         break;
    568                     case Gravity.CENTER_VERTICAL:
    569                         childTop = parentTop + (parentBottom - parentTop - height) / 2 +
    570                         lp.topMargin - lp.bottomMargin;
    571                         break;
    572                     case Gravity.BOTTOM:
    573                         childTop = parentBottom - height - lp.bottomMargin;
    574                         break;
    575                     default:
    576                         childTop = parentTop + lp.topMargin;
    577                 }
    578 
    579                 child.layout(childLeft, childTop, childLeft + width, childTop + height);
    580             }
    581         }
    582     }
    583 
    584     /**
    585      * {@inheritDoc}
    586      */
    587     @Override
    588     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    589         super.onSizeChanged(w, h, oldw, oldh);
    590         mForegroundBoundsChanged = true;
    591     }
    592 
    593     /**
    594      * {@inheritDoc}
    595      */
    596     @Override
    597     public void draw(Canvas canvas) {
    598         super.draw(canvas);
    599 
    600         if (mForeground != null) {
    601             final Drawable foreground = mForeground;
    602 
    603             if (mForegroundBoundsChanged) {
    604                 mForegroundBoundsChanged = false;
    605                 final Rect selfBounds = mSelfBounds;
    606                 final Rect overlayBounds = mOverlayBounds;
    607 
    608                 final int w = mRight-mLeft;
    609                 final int h = mBottom-mTop;
    610 
    611                 if (mForegroundInPadding) {
    612                     selfBounds.set(0, 0, w, h);
    613                 } else {
    614                     selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
    615                 }
    616 
    617                 final int layoutDirection = getLayoutDirection();
    618                 Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
    619                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
    620                         layoutDirection);
    621                 foreground.setBounds(overlayBounds);
    622             }
    623 
    624             foreground.draw(canvas);
    625         }
    626     }
    627 
    628     /**
    629      * {@inheritDoc}
    630      */
    631     @Override
    632     public boolean gatherTransparentRegion(Region region) {
    633         boolean opaque = super.gatherTransparentRegion(region);
    634         if (region != null && mForeground != null) {
    635             applyDrawableToTransparentRegion(mForeground, region);
    636         }
    637         return opaque;
    638     }
    639 
    640     /**
    641      * Sets whether to consider all children, or just those in
    642      * the VISIBLE or INVISIBLE state, when measuring. Defaults to false.
    643      *
    644      * @param measureAll true to consider children marked GONE, false otherwise.
    645      * Default value is false.
    646      *
    647      * @attr ref android.R.styleable#FrameLayout_measureAllChildren
    648      */
    649     @android.view.RemotableViewMethod
    650     public void setMeasureAllChildren(boolean measureAll) {
    651         mMeasureAllChildren = measureAll;
    652     }
    653 
    654     /**
    655      * Determines whether all children, or just those in the VISIBLE or
    656      * INVISIBLE state, are considered when measuring.
    657      *
    658      * @return Whether all children are considered when measuring.
    659      *
    660      * @deprecated This method is deprecated in favor of
    661      * {@link #getMeasureAllChildren() getMeasureAllChildren()}, which was
    662      * renamed for consistency with
    663      * {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}.
    664      */
    665     @Deprecated
    666     public boolean getConsiderGoneChildrenWhenMeasuring() {
    667         return getMeasureAllChildren();
    668     }
    669 
    670     /**
    671      * Determines whether all children, or just those in the VISIBLE or
    672      * INVISIBLE state, are considered when measuring.
    673      *
    674      * @return Whether all children are considered when measuring.
    675      */
    676     public boolean getMeasureAllChildren() {
    677         return mMeasureAllChildren;
    678     }
    679 
    680     /**
    681      * {@inheritDoc}
    682      */
    683     @Override
    684     public LayoutParams generateLayoutParams(AttributeSet attrs) {
    685         return new FrameLayout.LayoutParams(getContext(), attrs);
    686     }
    687 
    688     @Override
    689     public boolean shouldDelayChildPressedState() {
    690         return false;
    691     }
    692 
    693     /**
    694      * {@inheritDoc}
    695      */
    696     @Override
    697     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
    698         return p instanceof LayoutParams;
    699     }
    700 
    701     @Override
    702     protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
    703         return new LayoutParams(p);
    704     }
    705 
    706 
    707     @Override
    708     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
    709         super.onInitializeAccessibilityEvent(event);
    710         event.setClassName(FrameLayout.class.getName());
    711     }
    712 
    713     @Override
    714     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
    715         super.onInitializeAccessibilityNodeInfo(info);
    716         info.setClassName(FrameLayout.class.getName());
    717     }
    718 
    719     /**
    720      * Per-child layout information for layouts that support margins.
    721      * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
    722      * for a list of all child view attributes that this class supports.
    723      *
    724      * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
    725      */
    726     public static class LayoutParams extends MarginLayoutParams {
    727         /**
    728          * The gravity to apply with the View to which these layout parameters
    729          * are associated.
    730          *
    731          * @see android.view.Gravity
    732          *
    733          * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
    734          */
    735         public int gravity = -1;
    736 
    737         /**
    738          * {@inheritDoc}
    739          */
    740         public LayoutParams(Context c, AttributeSet attrs) {
    741             super(c, attrs);
    742 
    743             TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
    744             gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
    745             a.recycle();
    746         }
    747 
    748         /**
    749          * {@inheritDoc}
    750          */
    751         public LayoutParams(int width, int height) {
    752             super(width, height);
    753         }
    754 
    755         /**
    756          * Creates a new set of layout parameters with the specified width, height
    757          * and weight.
    758          *
    759          * @param width the width, either {@link #MATCH_PARENT},
    760          *        {@link #WRAP_CONTENT} or a fixed size in pixels
    761          * @param height the height, either {@link #MATCH_PARENT},
    762          *        {@link #WRAP_CONTENT} or a fixed size in pixels
    763          * @param gravity the gravity
    764          *
    765          * @see android.view.Gravity
    766          */
    767         public LayoutParams(int width, int height, int gravity) {
    768             super(width, height);
    769             this.gravity = gravity;
    770         }
    771 
    772         /**
    773          * {@inheritDoc}
    774          */
    775         public LayoutParams(ViewGroup.LayoutParams source) {
    776             super(source);
    777         }
    778 
    779         /**
    780          * {@inheritDoc}
    781          */
    782         public LayoutParams(ViewGroup.MarginLayoutParams source) {
    783             super(source);
    784         }
    785 
    786         /**
    787          * Copy constructor. Clones the width, height, margin values, and
    788          * gravity of the source.
    789          *
    790          * @param source The layout params to copy from.
    791          */
    792         public LayoutParams(LayoutParams source) {
    793             super(source);
    794 
    795             this.gravity = source.gravity;
    796         }
    797     }
    798 }
    799