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 
FrameLayout(Context context)102     public FrameLayout(Context context) {
103         super(context);
104     }
105 
FrameLayout(Context context, AttributeSet attrs)106     public FrameLayout(Context context, AttributeSet attrs) {
107         this(context, attrs, 0);
108     }
109 
FrameLayout(Context context, AttributeSet attrs, int defStyleAttr)110     public FrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
111         this(context, attrs, defStyleAttr, 0);
112     }
113 
FrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)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      */
getForegroundGravity()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
setForegroundGravity(int foregroundGravity)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
setVisibility(@isibility int visibility)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
verifyDrawable(Drawable who)218     protected boolean verifyDrawable(Drawable who) {
219         return super.verifyDrawable(who) || (who == mForeground);
220     }
221 
222     @Override
jumpDrawablesToCurrentState()223     public void jumpDrawablesToCurrentState() {
224         super.jumpDrawablesToCurrentState();
225         if (mForeground != null) mForeground.jumpToCurrentState();
226     }
227 
228     /**
229      * {@inheritDoc}
230      */
231     @Override
drawableStateChanged()232     protected void drawableStateChanged() {
233         super.drawableStateChanged();
234         if (mForeground != null && mForeground.isStateful()) {
235             mForeground.setState(getDrawableState());
236         }
237     }
238 
239     @Override
drawableHotspotChanged(float x, float y)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
generateDefaultLayoutParams()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      */
setForeground(Drawable d)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      */
getForeground()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      */
setForegroundTintList(@ullable ColorStateList tint)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
getForegroundTintList()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      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)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
getForegroundTintMode()372     public PorterDuff.Mode getForegroundTintMode() {
373         return mForegroundTintMode;
374     }
375 
applyForegroundTint()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 
getPaddingLeftWithForeground()396     int getPaddingLeftWithForeground() {
397         return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
398             mPaddingLeft + mForegroundPaddingLeft;
399     }
400 
getPaddingRightWithForeground()401     int getPaddingRightWithForeground() {
402         return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) :
403             mPaddingRight + mForegroundPaddingRight;
404     }
405 
getPaddingTopWithForeground()406     private int getPaddingTopWithForeground() {
407         return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) :
408             mPaddingTop + mForegroundPaddingTop;
409     }
410 
getPaddingBottomWithForeground()411     private int getPaddingBottomWithForeground() {
412         return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
413             mPaddingBottom + mForegroundPaddingBottom;
414     }
415 
416 
417     /**
418      * {@inheritDoc}
419      */
420     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)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
onLayout(boolean changed, int left, int top, int right, int bottom)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 
layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity)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
onSizeChanged(int w, int h, int oldw, int oldh)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
draw(Canvas canvas)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
gatherTransparentRegion(Region region)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
setMeasureAllChildren(boolean measureAll)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
getConsiderGoneChildrenWhenMeasuring()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      */
getMeasureAllChildren()676     public boolean getMeasureAllChildren() {
677         return mMeasureAllChildren;
678     }
679 
680     /**
681      * {@inheritDoc}
682      */
683     @Override
generateLayoutParams(AttributeSet attrs)684     public LayoutParams generateLayoutParams(AttributeSet attrs) {
685         return new FrameLayout.LayoutParams(getContext(), attrs);
686     }
687 
688     @Override
shouldDelayChildPressedState()689     public boolean shouldDelayChildPressedState() {
690         return false;
691     }
692 
693     /**
694      * {@inheritDoc}
695      */
696     @Override
checkLayoutParams(ViewGroup.LayoutParams p)697     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
698         return p instanceof LayoutParams;
699     }
700 
701     @Override
generateLayoutParams(ViewGroup.LayoutParams p)702     protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
703         return new LayoutParams(p);
704     }
705 
706 
707     @Override
onInitializeAccessibilityEvent(AccessibilityEvent event)708     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
709         super.onInitializeAccessibilityEvent(event);
710         event.setClassName(FrameLayout.class.getName());
711     }
712 
713     @Override
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)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          */
LayoutParams(Context c, AttributeSet attrs)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          */
LayoutParams(int width, int height)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          */
LayoutParams(int width, int height, int gravity)767         public LayoutParams(int width, int height, int gravity) {
768             super(width, height);
769             this.gravity = gravity;
770         }
771 
772         /**
773          * {@inheritDoc}
774          */
LayoutParams(ViewGroup.LayoutParams source)775         public LayoutParams(ViewGroup.LayoutParams source) {
776             super(source);
777         }
778 
779         /**
780          * {@inheritDoc}
781          */
LayoutParams(ViewGroup.MarginLayoutParams source)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          */
LayoutParams(LayoutParams source)792         public LayoutParams(LayoutParams source) {
793             super(source);
794 
795             this.gravity = source.gravity;
796         }
797     }
798 }
799