alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (TableRow.java)

This example Android source code file (TableRow.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

android, attributeset, childrentracker, content, gone, illegalargumentexception, layoutparams, linearlayout, location_next, onhierarchychangelistener, override, sparseintarray, tablerow, ui, util, utilities, utils, view, visible, wrap_content

The TableRow.java Android example source code

/*
 * Copyright (C) 2007 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.util.SparseIntArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;


/**
 * <p>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}.</p>
 *
 * <p>The children of a TableRow do not need to specify the
 * <code>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}.</p>
 *
 * <p>
 * Also see {@link TableRow.LayoutParams android.widget.TableRow.LayoutParams}
 * for layout attributes </p>
 */
public class TableRow extends LinearLayout {
    private int mNumColumns = 0;
    private int[] mColumnWidths;
    private int[] mConstrainedColumnWidths;
    private SparseIntArray mColumnToChildIndex;

    private ChildrenTracker mChildrenTracker;

    /**
     * <p>Creates a new TableRow for the given context.

* * @param context the application environment */ public TableRow(Context context) { super(context); initTableRow(); } /** * <p>Creates a new TableRow for the given context and with the * specified set attributes.</p> * * @param context the application environment * @param attrs a collection of attributes */ public TableRow(Context context, AttributeSet attrs) { super(context, attrs); initTableRow(); } private void initTableRow() { OnHierarchyChangeListener oldListener = mOnHierarchyChangeListener; mChildrenTracker = new ChildrenTracker(); if (oldListener != null) { mChildrenTracker.setOnHierarchyChangeListener(oldListener); } super.setOnHierarchyChangeListener(mChildrenTracker); } /** * {@inheritDoc} */ @Override public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { mChildrenTracker.setOnHierarchyChangeListener(listener); } /** * <p>Collapses or restores a given column.

* * @param columnIndex the index of the column * @param collapsed true if the column must be collapsed, false otherwise * {@hide} */ void setColumnCollapsed(int columnIndex, boolean collapsed) { View child = getVirtualChildAt(columnIndex); if (child != null) { child.setVisibility(collapsed ? GONE : VISIBLE); } } /** * {@inheritDoc} */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // enforce horizontal layout measureHorizontal(widthMeasureSpec, heightMeasureSpec); } /** * {@inheritDoc} */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // enforce horizontal layout layoutHorizontal(); } /** * {@inheritDoc} */ @Override public View getVirtualChildAt(int i) { if (mColumnToChildIndex == null) { mapIndexAndColumns(); } final int deflectedIndex = mColumnToChildIndex.get(i, -1); if (deflectedIndex != -1) { return getChildAt(deflectedIndex); } return null; } /** * {@inheritDoc} */ @Override public int getVirtualChildCount() { if (mColumnToChildIndex == null) { mapIndexAndColumns(); } return mNumColumns; } private void mapIndexAndColumns() { 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; } } /** * {@inheritDoc} */ @Override int measureNullChild(int childIndex) { return mConstrainedColumnWidths[childIndex]; } /** * {@inheritDoc} */ @Override void measureChildBeforeLayout(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; switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.LEFT: // don't offset on X axis break; case Gravity.RIGHT: lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT]; break; case Gravity.CENTER_HORIZONTAL: lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT] / 2; break; } } 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); } } /** * {@inheritDoc} */ @Override int getChildrenSkipCount(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; } /** * {@inheritDoc} */ @Override int getLocationOffset(View child) { return ((TableRow.LayoutParams) child.getLayoutParams()).mOffset[LayoutParams.LOCATION]; } /** * {@inheritDoc} */ @Override int getNextLocationOffset(View child) { return ((TableRow.LayoutParams) child.getLayoutParams()).mOffset[LayoutParams.LOCATION_NEXT]; } /** * <p>Measures the preferred width of each child, including its margins.

* * @param widthMeasureSpec the width constraint imposed by our parent * * @return an array of integers corresponding to the width of each cell, or * column, in this row * {@hide} */ int[] getColumnsWidths(int widthMeasureSpec) { 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); break; case LayoutParams.MATCH_PARENT: spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); break; default: spec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY); } child.measure(spec, spec); final int width = child.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin; columnWidths[i] = width; } else { columnWidths[i] = 0; } } else { columnWidths[i] = 0; } } return columnWidths; } /** * <p>Sets the width of all of the columns in this row. At layout time, * this row sets a fixed width, as defined by <code>columnWidths, * on each child (or cell, or column.)</p> * * @param columnWidths the fixed width of each column that this row must * honor * @throws IllegalArgumentException when columnWidths' length is smaller * than the number of children in this row * {@hide} */ void setColumnsWidthConstraints(int[] columnWidths) { if (columnWidths == null || columnWidths.length < getVirtualChildCount()) { throw new IllegalArgumentException( "columnWidths should be >= getVirtualChildCount()"); } mConstrainedColumnWidths = columnWidths; } /** * {@inheritDoc} */ @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new TableRow.LayoutParams(getContext(), attrs); } /** * 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. */ @Override protected LinearLayout.LayoutParams generateDefaultLayoutParams() { return new LayoutParams(); } /** * {@inheritDoc} */ @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { return p instanceof TableRow.LayoutParams; } /** * {@inheritDoc} */ @Override protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { return new LayoutParams(p); } /** * <p>Set of layout parameters used in table rows.

* * @see android.widget.TableLayout.LayoutParams * * @attr ref android.R.styleable#TableRow_Cell_layout_column * @attr ref android.R.styleable#TableRow_Cell_layout_span */ public static class LayoutParams extends LinearLayout.LayoutParams { /** * <p>The column index of the cell represented by the widget.

*/ @ViewDebug.ExportedProperty public int column; /** * <p>The number of columns the widgets spans over.

*/ @ViewDebug.ExportedProperty public int span; private static final int LOCATION = 0; private static final int LOCATION_NEXT = 1; private int[] mOffset = new int[2]; /** * {@inheritDoc} */ public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TableRow_Cell); column = a.getInt(com.android.internal.R.styleable.TableRow_Cell_layout_column, -1); span = a.getInt(com.android.internal.R.styleable.TableRow_Cell_layout_span, 1); if (span <= 1) { span = 1; } a.recycle(); } /** * <p>Sets the child width and the child height.

* * @param w the desired width * @param h the desired height */ public LayoutParams(int w, int h) { super(w, h); column = -1; span = 1; } /** * <p>Sets the child width, height and weight.

* * @param w the desired width * @param h the desired height * @param initWeight the desired weight */ public LayoutParams(int w, int h, float initWeight) { super(w, h, initWeight); column = -1; span = 1; } /** * <p>Sets the child width to {@link android.view.ViewGroup.LayoutParams} * and the child height to * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p> */ public LayoutParams() { super(MATCH_PARENT, WRAP_CONTENT); column = -1; span = 1; } /** * <p>Puts the view in the specified column.

* * <p>Sets the child width to {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} * and the child height to * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p> * * @param column the column index for the view */ public LayoutParams(int column) { this(); this.column = column; } /** * {@inheritDoc} */ public LayoutParams(ViewGroup.LayoutParams p) { super(p); } /** * {@inheritDoc} */ public LayoutParams(MarginLayoutParams source) { super(source); } @Override protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { // We don't want to force users to specify a layout_width if (a.hasValue(widthAttr)) { width = a.getLayoutDimension(widthAttr, "layout_width"); } else { width = MATCH_PARENT; } // We don't want to force users to specify a layout_height if (a.hasValue(heightAttr)) { height = a.getLayoutDimension(heightAttr, "layout_height"); } else { height = WRAP_CONTENT; } } } // special transparent hierarchy change listener private class ChildrenTracker implements OnHierarchyChangeListener { private OnHierarchyChangeListener listener; private void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { this.listener = listener; } public void onChildViewAdded(View parent, View child) { // dirties the index to column map mColumnToChildIndex = null; if (this.listener != null) { this.listener.onChildViewAdded(parent, child); } } public void onChildViewRemoved(View parent, View child) { // dirties the index to column map mColumnToChildIndex = null; if (this.listener != null) { this.listener.onChildViewRemoved(parent, child); } } } }

Other Android examples (source code examples)

Here is a short list of links related to this Android TableRow.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.