| /* | |
| * Copyright (C) 2009 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 com.example.android.fixedgridlayout; | |
| 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.ViewGroup; | |
| import android.view.ViewDebug; | |
| /** | |
| * A layout that arranges its children in a grid. The size of the | |
| * cells is set by the {@link #setCellSize} method and the | |
| * android:cell_width and android:cell_height attributes in XML. | |
| * The number of rows and columns is determined at runtime. Each | |
| * cell contains exactly one view, and they flow in the natural | |
| * child order (the order in which they were added, or the index | |
| * in {@link #addViewAt}. Views can not span multiple cells. | |
| */ | |
| public class FixedGridLayout extends ViewGroup { | |
| int mCellWidth; | |
| int mCellHeight; | |
| public FixedGridLayout(Context context) { | |
| super(context); | |
| } | |
| public FixedGridLayout(Context context, AttributeSet attrs) { | |
| super(context, attrs); | |
| // Read the resource attributes. | |
| TypedArray a = context.obtainStyledAttributes( | |
| attrs, R.styleable.FixedGridLayout); | |
| mCellWidth = a.getDimensionPixelSize( | |
| R.styleable.FixedGridLayout_cellWidth, -1); | |
| mCellHeight = a.getDimensionPixelSize( | |
| R.styleable.FixedGridLayout_cellHeight, -1); | |
| a.recycle(); | |
| } | |
| public void setCellWidth(int px) { | |
| mCellWidth = px; | |
| requestLayout(); | |
| } | |
| public void setCellHeight(int px) { | |
| mCellHeight = px; | |
| requestLayout(); | |
| } | |
| @Override | |
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
| int cellWidthSpec = MeasureSpec.makeMeasureSpec(mCellWidth, | |
| MeasureSpec.AT_MOST); | |
| int cellHeightSpec = MeasureSpec.makeMeasureSpec(mCellHeight, | |
| MeasureSpec.AT_MOST); | |
| int count = getChildCount(); | |
| for (int index=0; index<count; index++) { | |
| final View child = getChildAt(index); | |
| child.measure(cellWidthSpec, cellHeightSpec); | |
| } | |
| // Use the size our parents gave us | |
| setMeasuredDimension(resolveSize(mCellWidth*count, widthMeasureSpec), | |
| resolveSize(mCellHeight*count, heightMeasureSpec)); | |
| } | |
| @Override | |
| protected void onLayout(boolean changed, int l, int t, int r, int b) { | |
| int cellWidth = mCellWidth; | |
| int cellHeight = mCellHeight; | |
| int columns = (r - l) / cellWidth; | |
| if (columns < 0) { | |
| columns = 1; | |
| } | |
| int x = 0; | |
| int y = 0; | |
| int i = 0; | |
| int count = getChildCount(); | |
| for (int index=0; index<count; index++) { | |
| final View child = getChildAt(index); | |
| int w = child.getMeasuredWidth(); | |
| int h = child.getMeasuredHeight(); | |
| int left = x + ((cellWidth-w)/2); | |
| int top = y + ((cellHeight-h)/2); | |
| child.layout(left, top, left+w, top+h); | |
| if (i >= (columns-1)) { | |
| // advance to next row | |
| i = 0; | |
| x = 0; | |
| y += cellHeight; | |
| } else { | |
| i++; | |
| x += cellWidth; | |
| } | |
| } | |
| } | |
| } | |