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
17package android.widget;
18
19import java.util.ArrayList;
20
21import android.annotation.Nullable;
22import android.content.Context;
23import android.content.res.ColorStateList;
24import android.content.res.TypedArray;
25import android.graphics.Canvas;
26import android.graphics.PorterDuff;
27import android.graphics.Rect;
28import android.graphics.Region;
29import android.graphics.drawable.Drawable;
30import android.util.AttributeSet;
31import android.view.Gravity;
32import android.view.RemotableViewMethod;
33import android.view.View;
34import android.view.ViewDebug;
35import android.view.ViewGroup;
36import android.view.accessibility.AccessibilityEvent;
37import android.view.accessibility.AccessibilityNodeInfo;
38import android.widget.RemoteViews.RemoteView;
39
40import 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
63public 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    }
389
390    int getPaddingLeftWithForeground() {
391        return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
392            mPaddingLeft + mForegroundPaddingLeft;
393    }
394
395    int getPaddingRightWithForeground() {
396        return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) :
397            mPaddingRight + mForegroundPaddingRight;
398    }
399
400    private int getPaddingTopWithForeground() {
401        return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) :
402            mPaddingTop + mForegroundPaddingTop;
403    }
404
405    private int getPaddingBottomWithForeground() {
406        return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
407            mPaddingBottom + mForegroundPaddingBottom;
408    }
409
410
411    /**
412     * {@inheritDoc}
413     */
414    @Override
415    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
416        int count = getChildCount();
417
418        final boolean measureMatchParentChildren =
419                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
420                MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
421        mMatchParentChildren.clear();
422
423        int maxHeight = 0;
424        int maxWidth = 0;
425        int childState = 0;
426
427        for (int i = 0; i < count; i++) {
428            final View child = getChildAt(i);
429            if (mMeasureAllChildren || child.getVisibility() != GONE) {
430                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
431                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
432                maxWidth = Math.max(maxWidth,
433                        child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
434                maxHeight = Math.max(maxHeight,
435                        child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
436                childState = combineMeasuredStates(childState, child.getMeasuredState());
437                if (measureMatchParentChildren) {
438                    if (lp.width == LayoutParams.MATCH_PARENT ||
439                            lp.height == LayoutParams.MATCH_PARENT) {
440                        mMatchParentChildren.add(child);
441                    }
442                }
443            }
444        }
445
446        // Account for padding too
447        maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground();
448        maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground();
449
450        // Check against our minimum height and width
451        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
452        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
453
454        // Check against our foreground's minimum height and width
455        final Drawable drawable = getForeground();
456        if (drawable != null) {
457            maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
458            maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
459        }
460
461        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
462                resolveSizeAndState(maxHeight, heightMeasureSpec,
463                        childState << MEASURED_HEIGHT_STATE_SHIFT));
464
465        count = mMatchParentChildren.size();
466        if (count > 1) {
467            for (int i = 0; i < count; i++) {
468                final View child = mMatchParentChildren.get(i);
469
470                final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
471                int childWidthMeasureSpec;
472                int childHeightMeasureSpec;
473
474                if (lp.width == LayoutParams.MATCH_PARENT) {
475                    childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() -
476                            getPaddingLeftWithForeground() - getPaddingRightWithForeground() -
477                            lp.leftMargin - lp.rightMargin,
478                            MeasureSpec.EXACTLY);
479                } else {
480                    childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
481                            getPaddingLeftWithForeground() + getPaddingRightWithForeground() +
482                            lp.leftMargin + lp.rightMargin,
483                            lp.width);
484                }
485
486                if (lp.height == LayoutParams.MATCH_PARENT) {
487                    childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() -
488                            getPaddingTopWithForeground() - getPaddingBottomWithForeground() -
489                            lp.topMargin - lp.bottomMargin,
490                            MeasureSpec.EXACTLY);
491                } else {
492                    childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
493                            getPaddingTopWithForeground() + getPaddingBottomWithForeground() +
494                            lp.topMargin + lp.bottomMargin,
495                            lp.height);
496                }
497
498                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
499            }
500        }
501    }
502
503    /**
504     * {@inheritDoc}
505     */
506    @Override
507    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
508        layoutChildren(left, top, right, bottom, false /* no force left gravity */);
509    }
510
511    void layoutChildren(int left, int top, int right, int bottom,
512                                  boolean forceLeftGravity) {
513        final int count = getChildCount();
514
515        final int parentLeft = getPaddingLeftWithForeground();
516        final int parentRight = right - left - getPaddingRightWithForeground();
517
518        final int parentTop = getPaddingTopWithForeground();
519        final int parentBottom = bottom - top - getPaddingBottomWithForeground();
520
521        mForegroundBoundsChanged = true;
522
523        for (int i = 0; i < count; i++) {
524            final View child = getChildAt(i);
525            if (child.getVisibility() != GONE) {
526                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
527
528                final int width = child.getMeasuredWidth();
529                final int height = child.getMeasuredHeight();
530
531                int childLeft;
532                int childTop;
533
534                int gravity = lp.gravity;
535                if (gravity == -1) {
536                    gravity = DEFAULT_CHILD_GRAVITY;
537                }
538
539                final int layoutDirection = getLayoutDirection();
540                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
541                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
542
543                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
544                    case Gravity.CENTER_HORIZONTAL:
545                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
546                        lp.leftMargin - lp.rightMargin;
547                        break;
548                    case Gravity.RIGHT:
549                        if (!forceLeftGravity) {
550                            childLeft = parentRight - width - lp.rightMargin;
551                            break;
552                        }
553                    case Gravity.LEFT:
554                    default:
555                        childLeft = parentLeft + lp.leftMargin;
556                }
557
558                switch (verticalGravity) {
559                    case Gravity.TOP:
560                        childTop = parentTop + lp.topMargin;
561                        break;
562                    case Gravity.CENTER_VERTICAL:
563                        childTop = parentTop + (parentBottom - parentTop - height) / 2 +
564                        lp.topMargin - lp.bottomMargin;
565                        break;
566                    case Gravity.BOTTOM:
567                        childTop = parentBottom - height - lp.bottomMargin;
568                        break;
569                    default:
570                        childTop = parentTop + lp.topMargin;
571                }
572
573                child.layout(childLeft, childTop, childLeft + width, childTop + height);
574            }
575        }
576    }
577
578    /**
579     * {@inheritDoc}
580     */
581    @Override
582    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
583        super.onSizeChanged(w, h, oldw, oldh);
584        mForegroundBoundsChanged = true;
585    }
586
587    /**
588     * {@inheritDoc}
589     */
590    @Override
591    public void draw(Canvas canvas) {
592        super.draw(canvas);
593
594        if (mForeground != null) {
595            final Drawable foreground = mForeground;
596
597            if (mForegroundBoundsChanged) {
598                mForegroundBoundsChanged = false;
599                final Rect selfBounds = mSelfBounds;
600                final Rect overlayBounds = mOverlayBounds;
601
602                final int w = mRight-mLeft;
603                final int h = mBottom-mTop;
604
605                if (mForegroundInPadding) {
606                    selfBounds.set(0, 0, w, h);
607                } else {
608                    selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
609                }
610
611                final int layoutDirection = getLayoutDirection();
612                Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
613                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
614                        layoutDirection);
615                foreground.setBounds(overlayBounds);
616            }
617
618            foreground.draw(canvas);
619        }
620    }
621
622    /**
623     * {@inheritDoc}
624     */
625    @Override
626    public boolean gatherTransparentRegion(Region region) {
627        boolean opaque = super.gatherTransparentRegion(region);
628        if (region != null && mForeground != null) {
629            applyDrawableToTransparentRegion(mForeground, region);
630        }
631        return opaque;
632    }
633
634    /**
635     * Sets whether to consider all children, or just those in
636     * the VISIBLE or INVISIBLE state, when measuring. Defaults to false.
637     *
638     * @param measureAll true to consider children marked GONE, false otherwise.
639     * Default value is false.
640     *
641     * @attr ref android.R.styleable#FrameLayout_measureAllChildren
642     */
643    @android.view.RemotableViewMethod
644    public void setMeasureAllChildren(boolean measureAll) {
645        mMeasureAllChildren = measureAll;
646    }
647
648    /**
649     * Determines whether all children, or just those in the VISIBLE or
650     * INVISIBLE state, are considered when measuring.
651     *
652     * @return Whether all children are considered when measuring.
653     *
654     * @deprecated This method is deprecated in favor of
655     * {@link #getMeasureAllChildren() getMeasureAllChildren()}, which was
656     * renamed for consistency with
657     * {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}.
658     */
659    @Deprecated
660    public boolean getConsiderGoneChildrenWhenMeasuring() {
661        return getMeasureAllChildren();
662    }
663
664    /**
665     * Determines whether all children, or just those in the VISIBLE or
666     * INVISIBLE state, are considered when measuring.
667     *
668     * @return Whether all children are considered when measuring.
669     */
670    public boolean getMeasureAllChildren() {
671        return mMeasureAllChildren;
672    }
673
674    /**
675     * {@inheritDoc}
676     */
677    @Override
678    public LayoutParams generateLayoutParams(AttributeSet attrs) {
679        return new FrameLayout.LayoutParams(getContext(), attrs);
680    }
681
682    @Override
683    public boolean shouldDelayChildPressedState() {
684        return false;
685    }
686
687    /**
688     * {@inheritDoc}
689     */
690    @Override
691    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
692        return p instanceof LayoutParams;
693    }
694
695    @Override
696    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
697        return new LayoutParams(p);
698    }
699
700
701    @Override
702    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
703        super.onInitializeAccessibilityEvent(event);
704        event.setClassName(FrameLayout.class.getName());
705    }
706
707    @Override
708    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
709        super.onInitializeAccessibilityNodeInfo(info);
710        info.setClassName(FrameLayout.class.getName());
711    }
712
713    /**
714     * Per-child layout information for layouts that support margins.
715     * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
716     * for a list of all child view attributes that this class supports.
717     *
718     * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
719     */
720    public static class LayoutParams extends MarginLayoutParams {
721        /**
722         * The gravity to apply with the View to which these layout parameters
723         * are associated.
724         *
725         * @see android.view.Gravity
726         *
727         * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
728         */
729        public int gravity = -1;
730
731        /**
732         * {@inheritDoc}
733         */
734        public LayoutParams(Context c, AttributeSet attrs) {
735            super(c, attrs);
736
737            TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
738            gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
739            a.recycle();
740        }
741
742        /**
743         * {@inheritDoc}
744         */
745        public LayoutParams(int width, int height) {
746            super(width, height);
747        }
748
749        /**
750         * Creates a new set of layout parameters with the specified width, height
751         * and weight.
752         *
753         * @param width the width, either {@link #MATCH_PARENT},
754         *        {@link #WRAP_CONTENT} or a fixed size in pixels
755         * @param height the height, either {@link #MATCH_PARENT},
756         *        {@link #WRAP_CONTENT} or a fixed size in pixels
757         * @param gravity the gravity
758         *
759         * @see android.view.Gravity
760         */
761        public LayoutParams(int width, int height, int gravity) {
762            super(width, height);
763            this.gravity = gravity;
764        }
765
766        /**
767         * {@inheritDoc}
768         */
769        public LayoutParams(ViewGroup.LayoutParams source) {
770            super(source);
771        }
772
773        /**
774         * {@inheritDoc}
775         */
776        public LayoutParams(ViewGroup.MarginLayoutParams source) {
777            super(source);
778        }
779
780        /**
781         * Copy constructor. Clones the width, height, margin values, and
782         * gravity of the source.
783         *
784         * @param source The layout params to copy from.
785         */
786        public LayoutParams(LayoutParams source) {
787            super(source);
788
789            this.gravity = source.gravity;
790        }
791    }
792}
793