TableRow.javaAPI DocAndroid 5.1 API17974Thu Mar 12 22:22:10 GMT 2015android.widget


public class TableRow extends LinearLayout

A layout that arranges its children horizontally. A TableRow should always be used as a child of a {@link android.widget.TableLayout}. If a TableRow's parent is not a TableLayout, the TableRow will behave as an horizontal {@link android.widget.LinearLayout}.

The children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively {@link android.widget.TableLayout.LayoutParams#MATCH_PARENT} and {@link android.widget.TableLayout.LayoutParams#WRAP_CONTENT}.

Also see {@link TableRow.LayoutParams android.widget.TableRow.LayoutParams} for layout attributes

Fields Summary
private int
private int[]
private int[]
private android.util.SparseIntArray
private ChildrenTracker
Constructors Summary
public TableRow(android.content.Context context)

Creates a new TableRow for the given context.

context the application environment

public TableRow(android.content.Context context, android.util.AttributeSet attrs)

Creates a new TableRow for the given context and with the specified set attributes.

context the application environment
attrs a collection of attributes

        super(context, attrs);
Methods Summary
protected booleancheckLayoutParams(ViewGroup.LayoutParams p)

        return p instanceof TableRow.LayoutParams;
protected LinearLayout.LayoutParamsgenerateDefaultLayoutParams()
Returns a set of layout parameters with a width of {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and no spanning.

        return new LayoutParams();
public android.widget.TableRow$LayoutParamsgenerateLayoutParams(android.util.AttributeSet attrs)

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

        return new LayoutParams(p);
intgetChildrenSkipCount(android.view.View child, int index)

        LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();

        // when the span is 1 (default), we need to skip 0 child
        return layoutParams.span - 1;
int[]getColumnsWidths(int widthMeasureSpec)

Measures the preferred width of each child, including its margins.

widthMeasureSpec the width constraint imposed by our parent
an array of integers corresponding to the width of each cell, or column, in this row {@hide}

        final int numColumns = getVirtualChildCount();
        if (mColumnWidths == null || numColumns != mColumnWidths.length) {
            mColumnWidths = new int[numColumns];

        final int[] columnWidths = mColumnWidths;

        for (int i = 0; i < numColumns; i++) {
            final View child = getVirtualChildAt(i);
            if (child != null && child.getVisibility() != GONE) {
                final LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
                if (layoutParams.span == 1) {
                    int spec;
                    switch (layoutParams.width) {
                        case LayoutParams.WRAP_CONTENT:
                            spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT);
                        case LayoutParams.MATCH_PARENT:
                            spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                            spec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY);
                    child.measure(spec, spec);

                    final int width = child.getMeasuredWidth() + layoutParams.leftMargin +
                    columnWidths[i] = width;
                } else {
                    columnWidths[i] = 0;
            } else {
                columnWidths[i] = 0;

        return columnWidths;
intgetLocationOffset(android.view.View child)

        return ((TableRow.LayoutParams) child.getLayoutParams()).mOffset[LayoutParams.LOCATION];
intgetNextLocationOffset(android.view.View child)

        return ((TableRow.LayoutParams) child.getLayoutParams()).mOffset[LayoutParams.LOCATION_NEXT];
public android.view.ViewgetVirtualChildAt(int i)

        if (mColumnToChildIndex == null) {

        final int deflectedIndex = mColumnToChildIndex.get(i, -1);
        if (deflectedIndex != -1) {
            return getChildAt(deflectedIndex);

        return null;
public intgetVirtualChildCount()

        if (mColumnToChildIndex == null) {
        return mNumColumns;
private voidinitTableRow()

        OnHierarchyChangeListener oldListener = mOnHierarchyChangeListener;
        mChildrenTracker = new ChildrenTracker();
        if (oldListener != null) {
private voidmapIndexAndColumns()

        if (mColumnToChildIndex == null) {
            int virtualCount = 0;
            final int count = getChildCount();

            mColumnToChildIndex = new SparseIntArray();
            final SparseIntArray columnToChild = mColumnToChildIndex;

            for (int i = 0; i < count; i++) {
                final View child = getChildAt(i);
                final LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();

                if (layoutParams.column >= virtualCount) {
                    virtualCount = layoutParams.column;

                for (int j = 0; j < layoutParams.span; j++) {
                    columnToChild.put(virtualCount++, i);

            mNumColumns = virtualCount;
voidmeasureChildBeforeLayout(android.view.View child, int childIndex, int widthMeasureSpec, int totalWidth, int heightMeasureSpec, int totalHeight)

        if (mConstrainedColumnWidths != null) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            int measureMode = MeasureSpec.EXACTLY;
            int columnWidth = 0;

            final int span = lp.span;
            final int[] constrainedColumnWidths = mConstrainedColumnWidths;
            for (int i = 0; i < span; i++) {
                columnWidth += constrainedColumnWidths[childIndex + i];

            final int gravity = lp.gravity;
            final boolean isHorizontalGravity = Gravity.isHorizontal(gravity);

            if (isHorizontalGravity) {
                measureMode = MeasureSpec.AT_MOST;

            // no need to care about padding here,
            // ViewGroup.getChildMeasureSpec() would get rid of it anyway
            // because of the EXACTLY measure spec we use
            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
                    Math.max(0, columnWidth - lp.leftMargin - lp.rightMargin), measureMode
            int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                    mPaddingTop + mPaddingBottom + lp.topMargin +
                    lp .bottomMargin + totalHeight, lp.height);

            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

            if (isHorizontalGravity) {
                final int childWidth = child.getMeasuredWidth();
                lp.mOffset[LayoutParams.LOCATION_NEXT] = columnWidth - childWidth;

                final int layoutDirection = getLayoutDirection();
                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                    case Gravity.LEFT:
                        // don't offset on X axis
                    case Gravity.RIGHT:
                        lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT];
                    case Gravity.CENTER_HORIZONTAL:
                        lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT] / 2;
            } else {
                lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT] = 0;
        } else {
            // fail silently when column widths are not available
            super.measureChildBeforeLayout(child, childIndex, widthMeasureSpec,
                    totalWidth, heightMeasureSpec, totalHeight);
intmeasureNullChild(int childIndex)

        return mConstrainedColumnWidths[childIndex];
public voidonInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

public voidonInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)

protected voidonLayout(boolean changed, int l, int t, int r, int b)

        // enforce horizontal layout
        layoutHorizontal(l, t, r, b);
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        // enforce horizontal layout
        measureHorizontal(widthMeasureSpec, heightMeasureSpec);
voidsetColumnCollapsed(int columnIndex, boolean collapsed)

Collapses or restores a given column.

columnIndex the index of the column
collapsed true if the column must be collapsed, false otherwise {@hide}

        View child = getVirtualChildAt(columnIndex);
        if (child != null) {
            child.setVisibility(collapsed ? GONE : VISIBLE);
voidsetColumnsWidthConstraints(int[] columnWidths)

Sets the width of all of the columns in this row. At layout time, this row sets a fixed width, as defined by columnWidths, on each child (or cell, or column.)

columnWidths the fixed width of each column that this row must honor
IllegalArgumentException when columnWidths' length is smaller than the number of children in this row {@hide}

        if (columnWidths == null || columnWidths.length < getVirtualChildCount()) {
            throw new IllegalArgumentException(
                    "columnWidths should be >= getVirtualChildCount()");

        mConstrainedColumnWidths = columnWidths;
public voidsetOnHierarchyChangeListener(OnHierarchyChangeListener listener)