summaryrefslogtreecommitdiff
path: root/core/java/android/widget/FrameLayout.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
commit9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch)
treed88beb88001f2482911e3d28e43833b50e4b4e97 /core/java/android/widget/FrameLayout.java
parentd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff)
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/widget/FrameLayout.java')
-rw-r--r--core/java/android/widget/FrameLayout.java450
1 files changed, 450 insertions, 0 deletions
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
new file mode 100644
index 000000000000..8aafee2118f9
--- /dev/null
+++ b/core/java/android/widget/FrameLayout.java
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Gravity;
+import android.widget.RemoteViews.RemoteView;
+
+
+/**
+ * FrameLayout is designed to block out an area on the screen to display
+ * a single item. You can add multiple children to a FrameLayout, but all
+ * children are pegged to the top left of the screen.
+ * Children are drawn in a stack, with the most recently added child on top.
+ * The size of the frame layout is the size of its largest child (plus padding), visible
+ * or not (if the FrameLayout's parent permits). Views that are 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
+ */
+@RemoteView
+public class FrameLayout extends ViewGroup {
+ boolean mMeasureAllChildren = false;
+
+ private Drawable mForeground;
+ private int mForegroundPaddingLeft = 0;
+ private int mForegroundPaddingTop = 0;
+ private int mForegroundPaddingRight = 0;
+ private int mForegroundPaddingBottom = 0;
+
+ private final Rect mSelfBounds = new Rect();
+ private final Rect mOverlayBounds = new Rect();
+ private int mForegroundGravity = Gravity.FILL;
+
+ public FrameLayout(Context context) {
+ super(context);
+ }
+
+ public FrameLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FrameLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout,
+ defStyle, 0);
+
+ 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);
+ }
+
+ mForegroundGravity = a.getInt(com.android.internal.R.styleable.FrameLayout_foregroundGravity,
+ mForegroundGravity);
+
+ a.recycle();
+ }
+
+ /**
+ * Describes how the foreground is positioned. Defaults to FILL.
+ *
+ * @param foregroundGravity See {@link android.view.Gravity}
+ *
+ * @attr ref android.R.styleable#FrameLayout_foregroundGravity
+ */
+ @android.view.RemotableViewMethod
+ public void setForegroundGravity(int foregroundGravity) {
+ if (mForegroundGravity != foregroundGravity) {
+ if ((foregroundGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
+ foregroundGravity |= Gravity.LEFT;
+ }
+
+ if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
+ foregroundGravity |= Gravity.TOP;
+ }
+
+ mForegroundGravity = foregroundGravity;
+ requestLayout();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || (who == mForeground);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+ if (mForeground != null && mForeground.isStateful()) {
+ mForeground.setState(getDrawableState());
+ }
+ }
+
+ /**
+ * Returns a set of layout parameters with a width of
+ * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT},
+ * and a height of {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}.
+ */
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ }
+
+ /**
+ * Supply a Drawable that is to be rendered on top of all of the child
+ * views in the frame layout. Any padding in the Drawable will be taken
+ * into account by ensuring that the children are inset to be placed
+ * inside of the padding area.
+ *
+ * @param drawable The Drawable to be drawn on top of the children.
+ *
+ * @attr ref android.R.styleable#FrameLayout_foreground
+ */
+ public void setForeground(Drawable drawable) {
+ if (mForeground != drawable) {
+ if (mForeground != null) {
+ mForeground.setCallback(null);
+ unscheduleDrawable(mForeground);
+ }
+
+ mForeground = drawable;
+ mForegroundPaddingLeft = 0;
+ mForegroundPaddingTop = 0;
+ mForegroundPaddingRight = 0;
+ mForegroundPaddingBottom = 0;
+
+ if (drawable != null) {
+ setWillNotDraw(false);
+ drawable.setCallback(this);
+ if (drawable.isStateful()) {
+ drawable.setState(getDrawableState());
+ }
+ Rect padding = new Rect();
+ if (drawable.getPadding(padding)) {
+ mForegroundPaddingLeft = padding.left;
+ mForegroundPaddingTop = padding.top;
+ mForegroundPaddingRight = padding.right;
+ mForegroundPaddingBottom = padding.bottom;
+ }
+ } else {
+ setWillNotDraw(true);
+ }
+ requestLayout();
+ invalidate();
+ }
+ }
+
+ /**
+ * Returns the drawable used as the foreground of this FrameLayout. The
+ * foreground drawable, if non-null, is always drawn on top of the children.
+ *
+ * @return A Drawable or null if no foreground was set.
+ */
+ public Drawable getForeground() {
+ return mForeground;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int count = getChildCount();
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+
+ // Find rightmost and bottommost child
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (mMeasureAllChildren || child.getVisibility() != GONE) {
+ measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
+ maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
+ }
+ }
+
+ // Account for padding too
+ maxWidth += mPaddingLeft + mPaddingRight + mForegroundPaddingLeft + mForegroundPaddingRight;
+ maxHeight += mPaddingTop + mPaddingBottom + mForegroundPaddingTop + mForegroundPaddingBottom;
+
+ // 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(resolveSize(maxWidth, widthMeasureSpec),
+ resolveSize(maxHeight, heightMeasureSpec));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ final int count = getChildCount();
+
+ final int parentLeft = mPaddingLeft + mForegroundPaddingLeft;
+ final int parentRight = right - left - mPaddingRight - mForegroundPaddingRight;
+
+ final int parentTop = mPaddingTop + mForegroundPaddingTop;
+ final int parentBottom = bottom - top - mPaddingBottom - mForegroundPaddingBottom;
+
+ 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 = parentLeft;
+ int childTop = parentTop;
+
+ final int gravity = lp.gravity;
+
+ if (gravity != -1) {
+ final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+ switch (horizontalGravity) {
+ case Gravity.LEFT:
+ childLeft = parentLeft + lp.leftMargin;
+ break;
+ case Gravity.CENTER_HORIZONTAL:
+ childLeft = parentLeft + (parentRight - parentLeft + lp.leftMargin +
+ lp.rightMargin - width) / 2;
+ break;
+ case Gravity.RIGHT:
+ childLeft = parentRight - width - lp.rightMargin;
+ break;
+ default:
+ childLeft = parentLeft + lp.leftMargin;
+ }
+
+ switch (verticalGravity) {
+ case Gravity.TOP:
+ childTop = parentTop + lp.topMargin;
+ break;
+ case Gravity.CENTER_VERTICAL:
+ childTop = parentTop + (parentBottom - parentTop + lp.topMargin +
+ lp.bottomMargin - height) / 2;
+ break;
+ case Gravity.BOTTOM:
+ childTop = parentBottom - height - lp.bottomMargin;
+ break;
+ default:
+ childTop = parentTop + lp.topMargin;
+ }
+ }
+
+ child.layout(childLeft, childTop, childLeft + width, childTop + height);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ final Drawable foreground = mForeground;
+ if (foreground != null) {
+ final Rect selfBounds = mSelfBounds;
+ final Rect overlayBounds = mOverlayBounds;
+
+ selfBounds.set(0, 0, w, h);
+ Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
+ foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
+
+ foreground.setBounds(overlayBounds);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+
+ if (mForeground != null) {
+ mForeground.draw(canvas);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean gatherTransparentRegion(Region region) {
+ boolean opaque = super.gatherTransparentRegion(region);
+ if (region != null && mForeground != null) {
+ applyDrawableToTransparentRegion(mForeground, region);
+ }
+ return opaque;
+ }
+
+ /**
+ * Determines whether to measure 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
+ */
+ @android.view.RemotableViewMethod
+ public void setMeasureAllChildren(boolean measureAll) {
+ mMeasureAllChildren = measureAll;
+ }
+
+ /**
+ * Determines whether to measure all children or just those in
+ * the VISIBLE or INVISIBLE state when measuring.
+ */
+ public boolean getConsiderGoneChildrenWhenMeasuring() {
+ return mMeasureAllChildren;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new FrameLayout.LayoutParams(getContext(), attrs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ /**
+ * Per-child layout information for layouts that support margins.
+ * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
+ * for a list of all child view attributes that this class supports.
+ */
+ public static class LayoutParams extends MarginLayoutParams {
+ /**
+ * The gravity to apply with the View to which these layout parameters
+ * are associated.
+ *
+ * @see android.view.Gravity
+ */
+ public int gravity = -1;
+
+ /**
+ * {@inheritDoc}
+ */
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+
+ TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
+ gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
+ a.recycle();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ /**
+ * Creates a new set of layout parameters with the specified width, height
+ * and weight.
+ *
+ * @param width the width, either {@link #FILL_PARENT},
+ * {@link #WRAP_CONTENT} or a fixed size in pixels
+ * @param height the height, either {@link #FILL_PARENT},
+ * {@link #WRAP_CONTENT} or a fixed size in pixels
+ * @param gravity the gravity
+ *
+ * @see android.view.Gravity
+ */
+ public LayoutParams(int width, int height, int gravity) {
+ super(width, height);
+ this.gravity = gravity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LayoutParams(ViewGroup.MarginLayoutParams source) {
+ super(source);
+ }
+ }
+}
+