diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
| commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/widget/RelativeLayout.java | |
| parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/widget/RelativeLayout.java')
| -rw-r--r-- | core/java/android/widget/RelativeLayout.java | 954 |
1 files changed, 0 insertions, 954 deletions
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java deleted file mode 100644 index ba63ec356b1a..000000000000 --- a/core/java/android/widget/RelativeLayout.java +++ /dev/null @@ -1,954 +0,0 @@ -/* - * 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.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.view.Gravity; -import android.widget.RemoteViews.RemoteView; -import android.graphics.Rect; -import com.android.internal.R; - - -/** - * A Layout where the positions of the children can be described in relation to each other or to the - * parent. For the sake of efficiency, the relations between views are evaluated in one pass, so if - * view Y is dependent on the position of view X, make sure the view X comes first in the layout. - * - * <p> - * Note that you cannot have a circular dependency between the size of the RelativeLayout and the - * position of its children. For example, you cannot have a RelativeLayout whose height is set to - * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} and a child set to - * {@link #ALIGN_PARENT_BOTTOM}. - * </p> - * - * <p> - * Also see {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams} for - * layout attributes - * </p> - * - * @attr ref android.R.styleable#RelativeLayout_gravity - * @attr ref android.R.styleable#RelativeLayout_ignoreGravity - */ -@RemoteView -public class RelativeLayout extends ViewGroup { - public static final int TRUE = -1; - - /** - * Rule that aligns a child's right edge with another child's left edge. - */ - public static final int LEFT_OF = 0; - /** - * Rule that aligns a child's left edge with another child's right edge. - */ - public static final int RIGHT_OF = 1; - /** - * Rule that aligns a child's bottom edge with another child's top edge. - */ - public static final int ABOVE = 2; - /** - * Rule that aligns a child's top edge with another child's bottom edge. - */ - public static final int BELOW = 3; - - /** - * Rule that aligns a child's baseline with another child's baseline. - */ - public static final int ALIGN_BASELINE = 4; - /** - * Rule that aligns a child's left edge with another child's left edge. - */ - public static final int ALIGN_LEFT = 5; - /** - * Rule that aligns a child's top edge with another child's top edge. - */ - public static final int ALIGN_TOP = 6; - /** - * Rule that aligns a child's right edge with another child's right edge. - */ - public static final int ALIGN_RIGHT = 7; - /** - * Rule that aligns a child's bottom edge with another child's bottom edge. - */ - public static final int ALIGN_BOTTOM = 8; - - /** - * Rule that aligns the child's left edge with its RelativeLayout - * parent's left edge. - */ - public static final int ALIGN_PARENT_LEFT = 9; - /** - * Rule that aligns the child's top edge with its RelativeLayout - * parent's top edge. - */ - public static final int ALIGN_PARENT_TOP = 10; - /** - * Rule that aligns the child's right edge with its RelativeLayout - * parent's right edge. - */ - public static final int ALIGN_PARENT_RIGHT = 11; - /** - * Rule that aligns the child's bottom edge with its RelativeLayout - * parent's bottom edge. - */ - public static final int ALIGN_PARENT_BOTTOM = 12; - - /** - * Rule that centers the child with respect to the bounds of its - * RelativeLayout parent. - */ - public static final int CENTER_IN_PARENT = 13; - /** - * Rule that centers the child horizontally with respect to the - * bounds of its RelativeLayout parent. - */ - public static final int CENTER_HORIZONTAL = 14; - /** - * Rule that centers the child vertically with respect to the - * bounds of its RelativeLayout parent. - */ - public static final int CENTER_VERTICAL = 15; - - private static final int VERB_COUNT = 16; - - private View mBaselineView = null; - private boolean mHasBaselineAlignedChild; - - private int mGravity = Gravity.LEFT | Gravity.TOP; - private final Rect mContentBounds = new Rect(); - private final Rect mSelfBounds = new Rect(); - private int mIgnoreGravity; - - public RelativeLayout(Context context) { - super(context); - } - - public RelativeLayout(Context context, AttributeSet attrs) { - super(context, attrs); - initFromAttributes(context, attrs); - } - - public RelativeLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initFromAttributes(context, attrs); - } - - private void initFromAttributes(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RelativeLayout); - mIgnoreGravity = a.getResourceId(R.styleable.RelativeLayout_ignoreGravity, View.NO_ID); - mGravity = a.getInt(R.styleable.RelativeLayout_gravity, mGravity); - a.recycle(); - } - - /** - * Defines which View is ignored when the gravity is applied. This setting has no - * effect if the gravity is <code>Gravity.LEFT | Gravity.TOP</code>. - * - * @param viewId The id of the View to be ignored by gravity, or 0 if no View - * should be ignored. - * - * @see #setGravity(int) - * - * @attr ref android.R.styleable#RelativeLayout_ignoreGravity - */ - @android.view.RemotableViewMethod - public void setIgnoreGravity(int viewId) { - mIgnoreGravity = viewId; - } - - /** - * Describes how the child views are positioned. Defaults to - * <code>Gravity.LEFT | Gravity.TOP</code>. - * - * @param gravity See {@link android.view.Gravity} - * - * @see #setHorizontalGravity(int) - * @see #setVerticalGravity(int) - * - * @attr ref android.R.styleable#RelativeLayout_gravity - */ - @android.view.RemotableViewMethod - public void setGravity(int gravity) { - if (mGravity != gravity) { - if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) { - gravity |= Gravity.LEFT; - } - - if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { - gravity |= Gravity.TOP; - } - - mGravity = gravity; - requestLayout(); - } - } - - @android.view.RemotableViewMethod - public void setHorizontalGravity(int horizontalGravity) { - final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK; - if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) { - mGravity = (mGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK) | gravity; - requestLayout(); - } - } - - @android.view.RemotableViewMethod - public void setVerticalGravity(int verticalGravity) { - final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK; - if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) { - mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity; - requestLayout(); - } - } - - @Override - public int getBaseline() { - return mBaselineView != null ? mBaselineView.getBaseline() : super.getBaseline(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int myWidth = -1; - int myHeight = -1; - - int width = 0; - int height = 0; - - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - // Record our dimensions if they are known; - if (widthMode != MeasureSpec.UNSPECIFIED) { - myWidth = widthSize; - } - - if (heightMode != MeasureSpec.UNSPECIFIED) { - myHeight = heightSize; - } - - if (widthMode == MeasureSpec.EXACTLY) { - width = myWidth; - } - - if (heightMode == MeasureSpec.EXACTLY) { - height = myHeight; - } - - int len = this.getChildCount(); - mHasBaselineAlignedChild = false; - - View ignore = null; - int gravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK; - final boolean horizontalGravity = gravity != Gravity.LEFT && gravity != 0; - gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK; - final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0; - - int left = Integer.MAX_VALUE; - int top = Integer.MAX_VALUE; - int right = Integer.MIN_VALUE; - int bottom = Integer.MIN_VALUE; - - if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) { - ignore = findViewById(mIgnoreGravity); - } - - for (int i = 0; i < len; i++) { - View child = getChildAt(i); - if (child.getVisibility() != GONE) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); - applySizeRules(params, myWidth, myHeight); - measureChild(child, params, myWidth, myHeight); - positionChild(child, params, myWidth, myHeight); - - if (widthMode != MeasureSpec.EXACTLY) { - width = Math.max(width, params.mRight); - } - if (heightMode != MeasureSpec.EXACTLY) { - height = Math.max(height, params.mBottom); - } - - if (child != ignore || verticalGravity) { - left = Math.min(left, params.mLeft - params.leftMargin); - top = Math.min(top, params.mTop - params.topMargin); - } - - if (child != ignore || horizontalGravity) { - right = Math.max(right, params.mRight + params.rightMargin); - bottom = Math.max(bottom, params.mBottom + params.bottomMargin); - } - } - } - - if (mHasBaselineAlignedChild) { - for (int i = 0; i < len; i++) { - View child = getChildAt(i); - if (child.getVisibility() != GONE) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); - alignBaseline(child, params); - - if (child != ignore || verticalGravity) { - left = Math.min(left, params.mLeft - params.leftMargin); - top = Math.min(top, params.mTop - params.topMargin); - } - - if (child != ignore || horizontalGravity) { - right = Math.max(right, params.mRight + params.rightMargin); - bottom = Math.max(bottom, params.mBottom + params.bottomMargin); - } - } - } - } - - if (widthMode != MeasureSpec.EXACTLY) { - // Width already has left padding in it since it was calculated by looking at - // the right of each child view - width += mPaddingRight; - - if (mLayoutParams.width >= 0) { - width = Math.max(width, mLayoutParams.width); - } - - width = Math.max(width, getSuggestedMinimumWidth()); - width = resolveSize(width, widthMeasureSpec); - } - if (heightMode != MeasureSpec.EXACTLY) { - // Height already has top padding in it since it was calculated by looking at - // the bottom of each child view - height += mPaddingBottom; - - if (mLayoutParams.height >= 0) { - height = Math.max(height, mLayoutParams.height); - } - - height = Math.max(height, getSuggestedMinimumHeight()); - height = resolveSize(height, heightMeasureSpec); - } - - if (horizontalGravity || verticalGravity) { - final Rect selfBounds = mSelfBounds; - selfBounds.set(mPaddingLeft, mPaddingTop, width - mPaddingRight, - height - mPaddingBottom); - - final Rect contentBounds = mContentBounds; - Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds); - - final int horizontalOffset = contentBounds.left - left; - final int verticalOffset = contentBounds.top - top; - if (horizontalOffset != 0 || verticalOffset != 0) { - for (int i = 0; i < len; i++) { - View child = getChildAt(i); - if (child.getVisibility() != GONE && child != ignore) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); - params.mLeft += horizontalOffset; - params.mRight += horizontalOffset; - params.mTop += verticalOffset; - params.mBottom += verticalOffset; - } - } - } - } - - setMeasuredDimension(width, height); - } - - private void alignBaseline(View child, LayoutParams params) { - int[] rules = params.getRules(); - int anchorBaseline = getRelatedViewBaseline(rules, ALIGN_BASELINE); - - if (anchorBaseline != -1) { - LayoutParams anchorParams = getRelatedViewParams(rules, ALIGN_BASELINE); - if (anchorParams != null) { - int offset = anchorParams.mTop + anchorBaseline; - int baseline = child.getBaseline(); - if (baseline != -1) { - offset -= baseline; - } - int height = params.mBottom - params.mTop; - params.mTop = offset; - params.mBottom = params.mTop + height; - } - } - - if (mBaselineView == null) { - mBaselineView = child; - } else { - LayoutParams lp = (LayoutParams) mBaselineView.getLayoutParams(); - if (params.mTop < lp.mTop || (params.mTop == lp.mTop && params.mLeft < lp.mLeft)) { - mBaselineView = child; - } - } - } - - /** - * Measure a child. The child should have left, top, right and bottom information - * stored in its LayoutParams. If any of these values is -1 it means that the view - * can extend up to the corresponding edge. - * - * @param child Child to measure - * @param params LayoutParams associated with child - * @param myWidth Width of the the RelativeLayout - * @param myHeight Height of the RelativeLayout - */ - private void measureChild(View child, LayoutParams params, int myWidth, - int myHeight) { - - int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft, - params.mRight, params.width, - params.leftMargin, params.rightMargin, - mPaddingLeft, mPaddingRight, - myWidth); - int childHeightMeasureSpec = getChildMeasureSpec(params.mTop, - params.mBottom, params.height, - params.topMargin, params.bottomMargin, - mPaddingTop, mPaddingBottom, - myHeight); - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } - - /** - * Get a measure spec that accounts for all of the constraints on this view. - * This includes size contstraints imposed by the RelativeLayout as well as - * the View's desired dimension. - * - * @param childStart The left or top field of the child's layout params - * @param childEnd The right or bottom field of the child's layout params - * @param childSize The child's desired size (the width or height field of - * the child's layout params) - * @param startMargin The left or top margin - * @param endMargin The right or bottom margin - * @param startPadding mPaddingLeft or mPaddingTop - * @param endPadding mPaddingRight or mPaddingBottom - * @param mySize The width or height of this view (the RelativeLayout) - * @return MeasureSpec for the child - */ - private int getChildMeasureSpec(int childStart, int childEnd, - int childSize, int startMargin, int endMargin, int startPadding, - int endPadding, int mySize) { - int childSpecMode = 0; - int childSpecSize = 0; - - // Figure out start and end bounds. - int tempStart = childStart; - int tempEnd = childEnd; - - // If the view did not express a layout constraint for an edge, use - // view's margins and our padding - if (tempStart < 0) { - tempStart = startPadding + startMargin; - } - if (tempEnd < 0) { - tempEnd = mySize - endPadding - endMargin; - } - - // Figure out maximum size available to this view - int maxAvailable = tempEnd - tempStart; - - if (childStart >= 0 && childEnd >= 0) { - // Constraints fixed both edges, so child must be an exact size - childSpecMode = MeasureSpec.EXACTLY; - childSpecSize = maxAvailable; - } else { - if (childSize >= 0) { - // Child wanted an exact size. Give as much as possible - childSpecMode = MeasureSpec.EXACTLY; - - if (maxAvailable >= 0) { - // We have a maxmum size in this dimension. - childSpecSize = Math.min(maxAvailable, childSize); - } else { - // We can grow in this dimension. - childSpecSize = childSize; - } - } else if (childSize == LayoutParams.FILL_PARENT) { - // Child wanted to be as big as possible. Give all availble - // space - childSpecMode = MeasureSpec.EXACTLY; - childSpecSize = maxAvailable; - } else if (childSize == LayoutParams.WRAP_CONTENT) { - // Child wants to wrap content. Use AT_MOST - // to communicate available space if we know - // our max size - if (maxAvailable >= 0) { - // We have a maxmum size in this dimension. - childSpecMode = MeasureSpec.AT_MOST; - childSpecSize = maxAvailable; - } else { - // We can grow in this dimension. Child can be as big as it - // wants - childSpecMode = MeasureSpec.UNSPECIFIED; - childSpecSize = 0; - } - } - } - - return MeasureSpec.makeMeasureSpec(childSpecSize, childSpecMode); - } - - /** - * After the child has been measured, assign it a position. Some views may - * already have final values for l,t,r,b. Others may have one or both edges - * unfixed (i.e. set to -1) in each dimension. These will get positioned - * based on which edge is fixed, the view's desired dimension, and whether - * or not it is centered. - * - * @param child Child to position - * @param params LayoutParams associated with child - * @param myWidth Width of the the RelativeLayout - * @param myHeight Height of the RelativeLayout - */ - private void positionChild(View child, LayoutParams params, int myWidth, int myHeight) { - int[] rules = params.getRules(); - - if (params.mLeft < 0 && params.mRight >= 0) { - // Right is fixed, but left varies - params.mLeft = params.mRight - child.getMeasuredWidth(); - } else if (params.mLeft >= 0 && params.mRight < 0) { - // Left is fixed, but right varies - params.mRight = params.mLeft + child.getMeasuredWidth(); - } else if (params.mLeft < 0 && params.mRight < 0) { - // Both left and right vary - if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_HORIZONTAL]) { - centerHorizontal(child, params, myWidth); - } else { - params.mLeft = mPaddingLeft + params.leftMargin; - params.mRight = params.mLeft + child.getMeasuredWidth(); - } - } - - if (params.mTop < 0 && params.mBottom >= 0) { - // Bottom is fixed, but top varies - params.mTop = params.mBottom - child.getMeasuredHeight(); - } else if (params.mTop >= 0 && params.mBottom < 0) { - // Top is fixed, but bottom varies - params.mBottom = params.mTop + child.getMeasuredHeight(); - } else if (params.mTop < 0 && params.mBottom < 0) { - // Both top and bottom vary - if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_VERTICAL]) { - centerVertical(child, params, myHeight); - } else { - params.mTop = mPaddingTop + params.topMargin; - params.mBottom = params.mTop + child.getMeasuredHeight(); - } - } - } - - /** - * Set l,t,r,b values in the LayoutParams for one view based on its layout rules. - * Big assumption #1: All antecedents of this view have been sized & positioned - * Big assumption #2: The dimensions of the parent view (the RelativeLayout) - * are already known if they are needed. - * - * @param childParams LayoutParams for the view being positioned - * @param myWidth Width of the the RelativeLayout - * @param myHeight Height of the RelativeLayout - */ - private void applySizeRules(LayoutParams childParams, int myWidth, int myHeight) { - int[] rules = childParams.getRules(); - RelativeLayout.LayoutParams anchorParams; - - // -1 indicated a "soft requirement" in that direction. For example: - // left=10, right=-1 means the view must start at 10, but can go as far as it wants to the right - // left =-1, right=10 means the view must end at 10, but can go as far as it wants to the left - // left=10, right=20 means the left and right ends are both fixed - childParams.mLeft = -1; - childParams.mRight = -1; - - anchorParams = getRelatedViewParams(rules, LEFT_OF); - if (anchorParams != null) { - childParams.mRight = anchorParams.mLeft - (anchorParams.leftMargin + - childParams.rightMargin); - } else if (childParams.alignWithParent && rules[LEFT_OF] != 0) { - if (myWidth >= 0) { - childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin; - } else { - // FIXME uh oh... - } - } - - anchorParams = getRelatedViewParams(rules, RIGHT_OF); - if (anchorParams != null) { - childParams.mLeft = anchorParams.mRight + (anchorParams.rightMargin + - childParams.leftMargin); - } else if (childParams.alignWithParent && rules[RIGHT_OF] != 0) { - childParams.mLeft = mPaddingLeft + childParams.leftMargin; - } - - anchorParams = getRelatedViewParams(rules, ALIGN_LEFT); - if (anchorParams != null) { - childParams.mLeft = anchorParams.mLeft + childParams.leftMargin; - } else if (childParams.alignWithParent && rules[ALIGN_LEFT] != 0) { - childParams.mLeft = mPaddingLeft + childParams.leftMargin; - } - - anchorParams = getRelatedViewParams(rules, ALIGN_RIGHT); - if (anchorParams != null) { - childParams.mRight = anchorParams.mRight - childParams.rightMargin; - } else if (childParams.alignWithParent && rules[ALIGN_RIGHT] != 0) { - if (myWidth >= 0) { - childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin; - } else { - // FIXME uh oh... - } - } - - if (0 != rules[ALIGN_PARENT_LEFT]) { - childParams.mLeft = mPaddingLeft + childParams.leftMargin; - } - - if (0 != rules[ALIGN_PARENT_RIGHT]) { - if (myWidth >= 0) { - childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin; - } else { - // FIXME uh oh... - } - } - - childParams.mTop = -1; - childParams.mBottom = -1; - - anchorParams = getRelatedViewParams(rules, ABOVE); - if (anchorParams != null) { - childParams.mBottom = anchorParams.mTop - (anchorParams.topMargin + - childParams.bottomMargin); - } else if (childParams.alignWithParent && rules[ABOVE] != 0) { - if (myHeight >= 0) { - childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin; - } else { - // FIXME uh oh... - } - } - - anchorParams = getRelatedViewParams(rules, BELOW); - if (anchorParams != null) { - childParams.mTop = anchorParams.mBottom + (anchorParams.bottomMargin + - childParams.topMargin); - } else if (childParams.alignWithParent && rules[BELOW] != 0) { - childParams.mTop = mPaddingTop + childParams.topMargin; - } - - anchorParams = getRelatedViewParams(rules, ALIGN_TOP); - if (anchorParams != null) { - childParams.mTop = anchorParams.mTop + childParams.topMargin; - } else if (childParams.alignWithParent && rules[ALIGN_TOP] != 0) { - childParams.mTop = mPaddingTop + childParams.topMargin; - } - - anchorParams = getRelatedViewParams(rules, ALIGN_BOTTOM); - if (anchorParams != null) { - childParams.mBottom = anchorParams.mBottom - childParams.bottomMargin; - } else if (childParams.alignWithParent && rules[ALIGN_BOTTOM] != 0) { - if (myHeight >= 0) { - childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin; - } else { - // FIXME uh oh... - } - } - - if (0 != rules[ALIGN_PARENT_TOP]) { - childParams.mTop = mPaddingTop + childParams.topMargin; - } - - if (0 != rules[ALIGN_PARENT_BOTTOM]) { - if (myHeight >= 0) { - childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin; - } else { - // FIXME uh oh... - } - } - - if (rules[ALIGN_BASELINE] != 0) { - mHasBaselineAlignedChild = true; - } - } - - private View getRelatedView(int[] rules, int relation) { - int id = rules[relation]; - if (id != 0) { - View v = findViewById(id); - if (v == null) { - return null; - } - - // Find the first non-GONE view up the chain - while (v.getVisibility() == View.GONE) { - rules = ((LayoutParams) v.getLayoutParams()).getRules(); - v = v.findViewById(rules[relation]); - if (v == null) { - return null; - } - } - - return v; - } - - return null; - } - - private LayoutParams getRelatedViewParams(int[] rules, int relation) { - View v = getRelatedView(rules, relation); - if (v != null) { - ViewGroup.LayoutParams params = v.getLayoutParams(); - if (params instanceof LayoutParams) { - return (LayoutParams) v.getLayoutParams(); - } - } - return null; - } - - private int getRelatedViewBaseline(int[] rules, int relation) { - View v = getRelatedView(rules, relation); - if (v != null) { - return v.getBaseline(); - } - return -1; - } - - private void centerHorizontal(View child, LayoutParams params, int myWidth) { - int childWidth = child.getMeasuredWidth(); - int left = (myWidth - childWidth) / 2; - - params.mLeft = left; - params.mRight = left + childWidth; - } - - private void centerVertical(View child, LayoutParams params, int myHeight) { - int childHeight = child.getMeasuredHeight(); - int top = (myHeight - childHeight) / 2; - - params.mTop = top; - params.mBottom = top + childHeight; - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - // The layout has actually already been performed and the positions - // cached. Apply the cached values to the children. - int count = getChildCount(); - - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - if (child.getVisibility() != GONE) { - RelativeLayout.LayoutParams st = - (RelativeLayout.LayoutParams) child.getLayoutParams(); - child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom); - - } - } - } - - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new RelativeLayout.LayoutParams(getContext(), attrs); - } - - /** - * Returns a set of layout parameters with a width of - * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}, - * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and no spanning. - */ - @Override - protected ViewGroup.LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - } - - // Override to allow type-checking of LayoutParams. - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof RelativeLayout.LayoutParams; - } - - @Override - protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - return new LayoutParams(p); - } - - /** - * Per-child layout information associated with RelativeLayout. - * - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignWithParentIfMissing - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toLeftOf - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toRightOf - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_above - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_below - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignBaseline - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignLeft - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignTop - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignRight - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignBottom - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentLeft - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentTop - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentRight - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentBottom - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerInParent - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerHorizontal - * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerVertical - */ - public static class LayoutParams extends ViewGroup.MarginLayoutParams { - private int[] mRules = new int[VERB_COUNT]; - private int mLeft, mTop, mRight, mBottom; - - /** - * When true, uses the parent as the anchor if the anchor doesn't exist or if - * the anchor's visibility is GONE. - */ - public boolean alignWithParent; - - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - - TypedArray a = c.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.RelativeLayout_Layout); - - final int[] rules = mRules; - - final int N = a.getIndexCount(); - for (int i = 0; i < N; i++) { - int attr = a.getIndex(i); - switch (attr) { - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignWithParentIfMissing: - alignWithParent = a.getBoolean(attr, false); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toLeftOf: - rules[LEFT_OF] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toRightOf: - rules[RIGHT_OF] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_above: - rules[ABOVE] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_below: - rules[BELOW] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBaseline: - rules[ALIGN_BASELINE] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignLeft: - rules[ALIGN_LEFT] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignTop: - rules[ALIGN_TOP] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignRight: - rules[ALIGN_RIGHT] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBottom: - rules[ALIGN_BOTTOM] = a.getResourceId(attr, 0); - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentLeft: - rules[ALIGN_PARENT_LEFT] = a.getBoolean(attr, false) ? TRUE : 0; - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentTop: - rules[ALIGN_PARENT_TOP] = a.getBoolean(attr, false) ? TRUE : 0; - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentRight: - rules[ALIGN_PARENT_RIGHT] = a.getBoolean(attr, false) ? TRUE : 0; - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentBottom: - rules[ALIGN_PARENT_BOTTOM] = a.getBoolean(attr, false) ? TRUE : 0; - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerInParent: - rules[CENTER_IN_PARENT] = a.getBoolean(attr, false) ? TRUE : 0; - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerHorizontal: - rules[CENTER_HORIZONTAL] = a.getBoolean(attr, false) ? TRUE : 0; - break; - case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical: - rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0; - break; - } - } - - a.recycle(); - } - - public LayoutParams(int w, int h) { - super(w, h); - } - - /** - * {@inheritDoc} - */ - public LayoutParams(ViewGroup.LayoutParams source) { - super(source); - } - - /** - * {@inheritDoc} - */ - public LayoutParams(ViewGroup.MarginLayoutParams source) { - super(source); - } - - @Override - public String debug(String output) { - return output + "ViewGroup.LayoutParams={ width=" + sizeToString(width) + - ", height=" + sizeToString(height) + " }"; - } - - /** - * Adds a layout rule to be interpreted by the RelativeLayout. This - * method should only be used for constraints that don't refer to another sibling - * (e.g., CENTER_IN_PARENT) or take a boolean value ({@link RelativeLayout#TRUE} - * for true or - for false). To specify a verb that takes a subject, use - * {@link #addRule(int, int)} instead. - * - * @param verb One of the verbs defined by - * {@link android.widget.RelativeLayout RelativeLayout}, such as - * ALIGN_WITH_PARENT_LEFT. - * @see #addRule(int, int) - */ - public void addRule(int verb) { - mRules[verb] = TRUE; - } - - /** - * Adds a layout rule to be interpreted by the RelativeLayout. Use this for - * verbs that take a target, such as a sibling (ALIGN_RIGHT) or a boolean - * value (VISIBLE). - * - * @param verb One of the verbs defined by - * {@link android.widget.RelativeLayout RelativeLayout}, such as - * ALIGN_WITH_PARENT_LEFT. - * @param anchor The id of another view to use as an anchor, - * or a boolean value(represented as {@link RelativeLayout#TRUE}) - * for true or 0 for false). For verbs that don't refer to another sibling - * (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1. - * @see #addRule(int) - */ - public void addRule(int verb, int anchor) { - mRules[verb] = anchor; - } - - /** - * Retrieves a complete list of all supported rules, where the index is the rule - * verb, and the element value is the value specified, or "false" if it was never - * set. - * - * @return the supported rules - * @see #addRule(int, int) - */ - public int[] getRules() { - return mRules; - } - } -} |
