1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.fixedgridlayout; 18 19 import android.content.Context; 20 import android.content.res.TypedArray; 21 import android.util.AttributeSet; 22 import android.util.SparseIntArray; 23 import android.view.Gravity; 24 import android.view.View; 25 import android.view.ViewGroup; 26 import android.view.ViewDebug; 27 28 /** 29 * A layout that arranges its children in a grid. The size of the 30 * cells is set by the {@link #setCellSize} method and the 31 * android:cell_width and android:cell_height attributes in XML. 32 * The number of rows and columns is determined at runtime. Each 33 * cell contains exactly one view, and they flow in the natural 34 * child order (the order in which they were added, or the index 35 * in {@link #addViewAt}. Views can not span multiple cells. 36 */ 37 public class FixedGridLayout extends ViewGroup { 38 int mCellWidth; 39 int mCellHeight; 40 41 public FixedGridLayout(Context context) { 42 super(context); 43 } 44 45 public FixedGridLayout(Context context, AttributeSet attrs) { 46 super(context, attrs); 47 48 // Read the resource attributes. 49 TypedArray a = context.obtainStyledAttributes( 50 attrs, R.styleable.FixedGridLayout); 51 mCellWidth = a.getDimensionPixelSize( 52 R.styleable.FixedGridLayout_cellWidth, -1); 53 mCellHeight = a.getDimensionPixelSize( 54 R.styleable.FixedGridLayout_cellHeight, -1); 55 a.recycle(); 56 } 57 58 public void setCellWidth(int px) { 59 mCellWidth = px; 60 requestLayout(); 61 } 62 63 public void setCellHeight(int px) { 64 mCellHeight = px; 65 requestLayout(); 66 } 67 68 @Override 69 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 70 int cellWidthSpec = MeasureSpec.makeMeasureSpec(mCellWidth, 71 MeasureSpec.AT_MOST); 72 int cellHeightSpec = MeasureSpec.makeMeasureSpec(mCellHeight, 73 MeasureSpec.AT_MOST); 74 75 int count = getChildCount(); 76 for (int index=0; index<count; index++) { 77 final View child = getChildAt(index); 78 child.measure(cellWidthSpec, cellHeightSpec); 79 } 80 // Use the size our parents gave us 81 setMeasuredDimension(resolveSize(mCellWidth*count, widthMeasureSpec), 82 resolveSize(mCellHeight*count, heightMeasureSpec)); 83 } 84 85 @Override 86 protected void onLayout(boolean changed, int l, int t, int r, int b) { 87 int cellWidth = mCellWidth; 88 int cellHeight = mCellHeight; 89 int columns = (r - l) / cellWidth; 90 if (columns < 0) { 91 columns = 1; 92 } 93 int x = 0; 94 int y = 0; 95 int i = 0; 96 int count = getChildCount(); 97 for (int index=0; index<count; index++) { 98 final View child = getChildAt(index); 99 100 int w = child.getMeasuredWidth(); 101 int h = child.getMeasuredHeight(); 102 103 int left = x + ((cellWidth-w)/2); 104 int top = y + ((cellHeight-h)/2); 105 106 child.layout(left, top, left+w, top+h); 107 if (i >= (columns-1)) { 108 // advance to next row 109 i = 0; 110 x = 0; 111 y += cellHeight; 112 } else { 113 i++; 114 x += cellWidth; 115 } 116 } 117 } 118 } 119 120