FileDocCategorySizeDatePackage
FrameLayout.javaAPI DocAndroid 5.1 API28564Thu Mar 12 22:22:10 GMT 2015android.widget

FrameLayout

public class FrameLayout extends android.view.ViewGroup
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organize child views in a way that's scalable to different screen sizes without the children overlapping each other. You can, however, add multiple children to a FrameLayout and control their position within the FrameLayout by assigning gravity to each child, using the {@code android:layout_gravity} attribute.

Child views are drawn in a stack, with the most recently added child on top. The size of the FrameLayout is the size of its largest child (plus padding), visible or not (if the FrameLayout's parent permits). Views that are {@link android.view.View#GONE} are used for sizing only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()} is set to true.

attr
ref android.R.styleable#FrameLayout_foreground
attr
ref android.R.styleable#FrameLayout_foregroundGravity
attr
ref android.R.styleable#FrameLayout_measureAllChildren

Fields Summary
private static final int
DEFAULT_CHILD_GRAVITY
boolean
mMeasureAllChildren
private android.graphics.drawable.Drawable
mForeground
private android.content.res.ColorStateList
mForegroundTintList
private PorterDuff.Mode
mForegroundTintMode
private boolean
mHasForegroundTint
private boolean
mHasForegroundTintMode
private int
mForegroundPaddingLeft
private int
mForegroundPaddingTop
private int
mForegroundPaddingRight
private int
mForegroundPaddingBottom
private final android.graphics.Rect
mSelfBounds
private final android.graphics.Rect
mOverlayBounds
private int
mForegroundGravity
protected boolean
mForegroundInPadding
{@hide}
boolean
mForegroundBoundsChanged
private final ArrayList
mMatchParentChildren
Constructors Summary
public FrameLayout(android.content.Context context)

    
       
        super(context);
    
public FrameLayout(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, 0);
    
public FrameLayout(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr)

        this(context, attrs, defStyleAttr, 0);
    
public FrameLayout(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)

        super(context, attrs, defStyleAttr, defStyleRes);

        final TypedArray a = context.obtainStyledAttributes(
                attrs, com.android.internal.R.styleable.FrameLayout, defStyleAttr, defStyleRes);

        mForegroundGravity = a.getInt(
                com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity);

        final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
        if (d != null) {
            setForeground(d);
        }
        
        if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
            setMeasureAllChildren(true);
        }

        if (a.hasValue(R.styleable.FrameLayout_foregroundTintMode)) {
            mForegroundTintMode = Drawable.parseTintMode(a.getInt(
                    R.styleable.FrameLayout_foregroundTintMode, -1), mForegroundTintMode);
            mHasForegroundTintMode = true;
        }

        if (a.hasValue(R.styleable.FrameLayout_foregroundTint)) {
            mForegroundTintList = a.getColorStateList(R.styleable.FrameLayout_foregroundTint);
            mHasForegroundTint = true;
        }

        mForegroundInPadding = a.getBoolean(R.styleable.FrameLayout_foregroundInsidePadding, true);

        a.recycle();

        applyForegroundTint();
    
Methods Summary
private voidapplyForegroundTint()

        if (mForeground != null && (mHasForegroundTint || mHasForegroundTintMode)) {
            mForeground = mForeground.mutate();

            if (mHasForegroundTint) {
                mForeground.setTintList(mForegroundTintList);
            }

            if (mHasForegroundTintMode) {
                mForeground.setTintMode(mForegroundTintMode);
            }

            // The drawable (or one of its children) may not have been
            // stateful before applying the tint, so let's try again.
            if (mForeground.isStateful()) {
                mForeground.setState(getDrawableState());
            }
        }
    
protected booleancheckLayoutParams(ViewGroup.LayoutParams p)
{@inheritDoc}

        return p instanceof LayoutParams;
    
public voiddraw(android.graphics.Canvas canvas)
{@inheritDoc}

        super.draw(canvas);

        if (mForeground != null) {
            final Drawable foreground = mForeground;

            if (mForegroundBoundsChanged) {
                mForegroundBoundsChanged = false;
                final Rect selfBounds = mSelfBounds;
                final Rect overlayBounds = mOverlayBounds;

                final int w = mRight-mLeft;
                final int h = mBottom-mTop;

                if (mForegroundInPadding) {
                    selfBounds.set(0, 0, w, h);
                } else {
                    selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
                }

                final int layoutDirection = getLayoutDirection();
                Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
                        layoutDirection);
                foreground.setBounds(overlayBounds);
            }
            
            foreground.draw(canvas);
        }
    
public voiddrawableHotspotChanged(float x, float y)

        super.drawableHotspotChanged(x, y);

        if (mForeground != null) {
            mForeground.setHotspot(x, y);
        }
    
protected voiddrawableStateChanged()
{@inheritDoc}

        super.drawableStateChanged();
        if (mForeground != null && mForeground.isStateful()) {
            mForeground.setState(getDrawableState());
        }
    
public booleangatherTransparentRegion(android.graphics.Region region)
{@inheritDoc}

        boolean opaque = super.gatherTransparentRegion(region);
        if (region != null && mForeground != null) {
            applyDrawableToTransparentRegion(mForeground, region);
        }
        return opaque;
    
protected android.widget.FrameLayout$LayoutParamsgenerateDefaultLayoutParams()
Returns a set of layout parameters with a width of {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, and a height of {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}.

        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    
public android.widget.FrameLayout$LayoutParamsgenerateLayoutParams(android.util.AttributeSet attrs)
{@inheritDoc}

        return new FrameLayout.LayoutParams(getContext(), attrs);        
    
protected ViewGroup.LayoutParamsgenerateLayoutParams(ViewGroup.LayoutParams p)

        return new LayoutParams(p);
    
public booleangetConsiderGoneChildrenWhenMeasuring()
Determines whether all children, or just those in the VISIBLE or INVISIBLE state, are considered when measuring.

return
Whether all children are considered when measuring.
deprecated
This method is deprecated in favor of {@link #getMeasureAllChildren() getMeasureAllChildren()}, which was renamed for consistency with {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}.

        return getMeasureAllChildren();
    
public android.graphics.drawable.DrawablegetForeground()
Returns the drawable used as the foreground of this FrameLayout. The foreground drawable, if non-null, is always drawn on top of the children.

return
A Drawable or null if no foreground was set.

        return mForeground;
    
public intgetForegroundGravity()
Describes how the foreground is positioned.

return
foreground gravity.
see
#setForegroundGravity(int)
attr
ref android.R.styleable#FrameLayout_foregroundGravity

        return mForegroundGravity;
    
public android.content.res.ColorStateListgetForegroundTintList()

return
the tint applied to the foreground drawable
attr
ref android.R.styleable#FrameLayout_foregroundTint
see
#setForegroundTintList(ColorStateList)

        return mForegroundTintList;
    
public PorterDuff.ModegetForegroundTintMode()

return
the blending mode used to apply the tint to the foreground drawable
attr
ref android.R.styleable#FrameLayout_foregroundTintMode
see
#setForegroundTintMode(PorterDuff.Mode)

        return mForegroundTintMode;
    
public booleangetMeasureAllChildren()
Determines whether all children, or just those in the VISIBLE or INVISIBLE state, are considered when measuring.

return
Whether all children are considered when measuring.

        return mMeasureAllChildren;
    
private intgetPaddingBottomWithForeground()

        return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
            mPaddingBottom + mForegroundPaddingBottom;
    
intgetPaddingLeftWithForeground()

        return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
            mPaddingLeft + mForegroundPaddingLeft;
    
intgetPaddingRightWithForeground()

        return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) :
            mPaddingRight + mForegroundPaddingRight;
    
private intgetPaddingTopWithForeground()

        return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) :
            mPaddingTop + mForegroundPaddingTop;
    
public voidjumpDrawablesToCurrentState()

        super.jumpDrawablesToCurrentState();
        if (mForeground != null) mForeground.jumpToCurrentState();
    
voidlayoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity)

        final int count = getChildCount();

        final int parentLeft = getPaddingLeftWithForeground();
        final int parentRight = right - left - getPaddingRightWithForeground();

        final int parentTop = getPaddingTopWithForeground();
        final int parentBottom = bottom - top - getPaddingBottomWithForeground();

        mForegroundBoundsChanged = true;
        
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();

                final int width = child.getMeasuredWidth();
                final int height = child.getMeasuredHeight();

                int childLeft;
                int childTop;

                int gravity = lp.gravity;
                if (gravity == -1) {
                    gravity = DEFAULT_CHILD_GRAVITY;
                }

                final int layoutDirection = getLayoutDirection();
                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;

                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                    case Gravity.CENTER_HORIZONTAL:
                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
                        lp.leftMargin - lp.rightMargin;
                        break;
                    case Gravity.RIGHT:
                        if (!forceLeftGravity) {
                            childLeft = parentRight - width - lp.rightMargin;
                            break;
                        }
                    case Gravity.LEFT:
                    default:
                        childLeft = parentLeft + lp.leftMargin;
                }

                switch (verticalGravity) {
                    case Gravity.TOP:
                        childTop = parentTop + lp.topMargin;
                        break;
                    case Gravity.CENTER_VERTICAL:
                        childTop = parentTop + (parentBottom - parentTop - height) / 2 +
                        lp.topMargin - lp.bottomMargin;
                        break;
                    case Gravity.BOTTOM:
                        childTop = parentBottom - height - lp.bottomMargin;
                        break;
                    default:
                        childTop = parentTop + lp.topMargin;
                }

                child.layout(childLeft, childTop, childLeft + width, childTop + height);
            }
        }
    
public voidonInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

        super.onInitializeAccessibilityEvent(event);
        event.setClassName(FrameLayout.class.getName());
    
public voidonInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)

        super.onInitializeAccessibilityNodeInfo(info);
        info.setClassName(FrameLayout.class.getName());
    
protected voidonLayout(boolean changed, int left, int top, int right, int bottom)
{@inheritDoc}

        layoutChildren(left, top, right, bottom, false /* no force left gravity */);
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)
{@inheritDoc}

        int count = getChildCount();

        final boolean measureMatchParentChildren =
                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
                MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
        mMatchParentChildren.clear();

        int maxHeight = 0;
        int maxWidth = 0;
        int childState = 0;

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (mMeasureAllChildren || child.getVisibility() != GONE) {
                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                maxWidth = Math.max(maxWidth,
                        child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
                maxHeight = Math.max(maxHeight,
                        child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
                childState = combineMeasuredStates(childState, child.getMeasuredState());
                if (measureMatchParentChildren) {
                    if (lp.width == LayoutParams.MATCH_PARENT ||
                            lp.height == LayoutParams.MATCH_PARENT) {
                        mMatchParentChildren.add(child);
                    }
                }
            }
        }

        // Account for padding too
        maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground();
        maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground();

        // Check against our minimum height and width
        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

        // Check against our foreground's minimum height and width
        final Drawable drawable = getForeground();
        if (drawable != null) {
            maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
            maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
        }

        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                resolveSizeAndState(maxHeight, heightMeasureSpec,
                        childState << MEASURED_HEIGHT_STATE_SHIFT));

        count = mMatchParentChildren.size();
        if (count > 1) {
            for (int i = 0; i < count; i++) {
                final View child = mMatchParentChildren.get(i);

                final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                int childWidthMeasureSpec;
                int childHeightMeasureSpec;
                
                if (lp.width == LayoutParams.MATCH_PARENT) {
                    childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() -
                            getPaddingLeftWithForeground() - getPaddingRightWithForeground() -
                            lp.leftMargin - lp.rightMargin,
                            MeasureSpec.EXACTLY);
                } else {
                    childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
                            getPaddingLeftWithForeground() + getPaddingRightWithForeground() +
                            lp.leftMargin + lp.rightMargin,
                            lp.width);
                }
                
                if (lp.height == LayoutParams.MATCH_PARENT) {
                    childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() -
                            getPaddingTopWithForeground() - getPaddingBottomWithForeground() -
                            lp.topMargin - lp.bottomMargin,
                            MeasureSpec.EXACTLY);
                } else {
                    childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                            getPaddingTopWithForeground() + getPaddingBottomWithForeground() +
                            lp.topMargin + lp.bottomMargin,
                            lp.height);
                }

                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
            }
        }
    
protected voidonSizeChanged(int w, int h, int oldw, int oldh)
{@inheritDoc}

        super.onSizeChanged(w, h, oldw, oldh);
        mForegroundBoundsChanged = true;
    
public voidsetForeground(android.graphics.drawable.Drawable d)
Supply a Drawable that is to be rendered on top of all of the child views in the frame layout. Any padding in the Drawable will be taken into account by ensuring that the children are inset to be placed inside of the padding area.

param
d The Drawable to be drawn on top of the children.
attr
ref android.R.styleable#FrameLayout_foreground

        if (mForeground != d) {
            if (mForeground != null) {
                mForeground.setCallback(null);
                unscheduleDrawable(mForeground);
            }

            mForeground = d;
            mForegroundPaddingLeft = 0;
            mForegroundPaddingTop = 0;
            mForegroundPaddingRight = 0;
            mForegroundPaddingBottom = 0;

            if (d != null) {
                setWillNotDraw(false);
                d.setCallback(this);
                d.setLayoutDirection(getLayoutDirection());
                if (d.isStateful()) {
                    d.setState(getDrawableState());
                }
                applyForegroundTint();
                if (mForegroundGravity == Gravity.FILL) {
                    Rect padding = new Rect();
                    if (d.getPadding(padding)) {
                        mForegroundPaddingLeft = padding.left;
                        mForegroundPaddingTop = padding.top;
                        mForegroundPaddingRight = padding.right;
                        mForegroundPaddingBottom = padding.bottom;
                    }
                }
            }  else {
                setWillNotDraw(true);
            }
            requestLayout();
            invalidate();
        }
    
public voidsetForegroundGravity(int foregroundGravity)
Describes how the foreground is positioned. Defaults to START and TOP.

param
foregroundGravity See {@link android.view.Gravity}
see
#getForegroundGravity()
attr
ref android.R.styleable#FrameLayout_foregroundGravity

        if (mForegroundGravity != foregroundGravity) {
            if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
                foregroundGravity |= Gravity.START;
            }

            if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
                foregroundGravity |= Gravity.TOP;
            }

            mForegroundGravity = foregroundGravity;


            if (mForegroundGravity == Gravity.FILL && mForeground != null) {
                Rect padding = new Rect();
                if (mForeground.getPadding(padding)) {
                    mForegroundPaddingLeft = padding.left;
                    mForegroundPaddingTop = padding.top;
                    mForegroundPaddingRight = padding.right;
                    mForegroundPaddingBottom = padding.bottom;
                }
            } else {
                mForegroundPaddingLeft = 0;
                mForegroundPaddingTop = 0;
                mForegroundPaddingRight = 0;
                mForegroundPaddingBottom = 0;
            }

            requestLayout();
        }
    
public voidsetForegroundTintList(android.content.res.ColorStateList tint)
Applies a tint to the foreground drawable. Does not modify the current tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.

Subsequent calls to {@link #setForeground(Drawable)} will automatically mutate the drawable and apply the specified tint and tint mode using {@link Drawable#setTintList(ColorStateList)}.

param
tint the tint to apply, may be {@code null} to clear tint
attr
ref android.R.styleable#FrameLayout_foregroundTint
see
#getForegroundTintList()
see
Drawable#setTintList(ColorStateList)

        mForegroundTintList = tint;
        mHasForegroundTint = true;

        applyForegroundTint();
    
public voidsetForegroundTintMode(PorterDuff.Mode tintMode)
Specifies the blending mode used to apply the tint specified by {@link #setForegroundTintList(ColorStateList)}} to the foreground drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.

param
tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
attr
ref android.R.styleable#FrameLayout_foregroundTintMode
see
#getForegroundTintMode()
see
Drawable#setTintMode(PorterDuff.Mode)

        mForegroundTintMode = tintMode;
        mHasForegroundTintMode = true;

        applyForegroundTint();
    
public voidsetMeasureAllChildren(boolean measureAll)
Sets whether to consider all children, or just those in the VISIBLE or INVISIBLE state, when measuring. Defaults to false.

param
measureAll true to consider children marked GONE, false otherwise. Default value is false.
attr
ref android.R.styleable#FrameLayout_measureAllChildren

        mMeasureAllChildren = measureAll;
    
public voidsetVisibility(int visibility)

        super.setVisibility(visibility);
        if (mForeground != null) {
            mForeground.setVisible(visibility == VISIBLE, false);
        }
    
public booleanshouldDelayChildPressedState()

        return false;
    
protected booleanverifyDrawable(android.graphics.drawable.Drawable who)
{@inheritDoc}

        return super.verifyDrawable(who) || (who == mForeground);