Skip to content

Instantly share code, notes, and snippets.

@DayS
Last active December 14, 2015 17:48
Show Gist options
  • Save DayS/ea0c22b60dd263443316 to your computer and use it in GitHub Desktop.
Save DayS/ea0c22b60dd263443316 to your computer and use it in GitHub Desktop.
Display views in a grid with customizable cells sizes an position
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class SimpleGridLayout extends ViewGroup {
private int cellMarginPx = 0;
private int columnCount = 2;
private int rowCount = -1;
public SimpleGridLayout(Context context) {
super(context);
init();
}
public SimpleGridLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SimpleGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
if (isInEditMode()) {
setColumnCount(2);
setRowCount(3);
for (int y = 0; y < getRowCount(); y++) {
for (int x = 0; x < getColumnCount(); x++) {
TextView textView = new TextView(getContext());
textView.setText(String.format("%d %d", x, y));
textView.setGravity(Gravity.CENTER);
addView(textView, new LayoutParams(x, 1, y, 1));
}
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int totalWidth = MeasureSpec.getSize(widthMeasureSpec);
int totalHeight = MeasureSpec.getSize(heightMeasureSpec);
int contentWidth = totalWidth - getPaddingLeft() - getPaddingRight();
int contentHeight;
if (hasUnlimitedRows()) {
contentHeight = 0;
} else {
contentHeight = totalHeight - getPaddingTop() - getPaddingBottom();
}
int cellBaseWidth = (contentWidth - (columnCount - 1) * cellMarginPx) / columnCount;
int cellBaseHeight;
if (hasUnlimitedRows()) {
cellBaseHeight = 0;
} else {
cellBaseHeight = (contentHeight - (rowCount - 1) * cellMarginPx) / rowCount;
}
int maxCellHeightForRow = 0;
for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
final View view = getChildAt(i);
final LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
int cellWidth = cellBaseWidth * layoutParams.colSpan + ((layoutParams.colSpan - 1) * cellMarginPx);
int cellWidthSpec = MeasureSpec.makeMeasureSpec(cellWidth, MeasureSpec.EXACTLY);
int cellHeightSpec;
if (hasUnlimitedRows()) {
cellHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
} else {
int cellHeight = cellBaseHeight * layoutParams.rowSpan + ((layoutParams.rowSpan - 1) * cellMarginPx);
cellHeightSpec = MeasureSpec.makeMeasureSpec(cellHeight, MeasureSpec.EXACTLY);
}
view.measure(cellWidthSpec, cellHeightSpec);
maxCellHeightForRow = Math.max(maxCellHeightForRow, view.getMeasuredHeight());
if (i > 0 && i % getColumnCount() == 0) {
contentHeight += maxCellHeightForRow;
}
}
contentHeight += maxCellHeightForRow;
if (hasUnlimitedRows()) {
setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY));
} else {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (getChildCount() == 0)
return;
int contentWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
int contentHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
int rowCount = this.rowCount;
if (hasUnlimitedRows()) {
rowCount = (int) Math.ceil(getChildCount() / (float) getColumnCount());
}
int cellBaseWidth = (contentWidth - (columnCount - 1) * cellMarginPx) / columnCount;
int cellBaseHeight = (contentHeight - (rowCount - 1) * cellMarginPx) / rowCount;
for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
final View view = getChildAt(i);
final LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
int childLeft = getPaddingLeft() + (cellBaseWidth + cellMarginPx) * layoutParams.colIndex;
int childTop = getPaddingTop() + (cellBaseHeight + cellMarginPx) * layoutParams.rowIndex;
int childWidth = view.getMeasuredWidth();
int childHeight = view.getMeasuredHeight();
view.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
}
public int getColumnCount() {
return columnCount;
}
public void setColumnCount(int columnCount) {
this.columnCount = columnCount;
}
public int getRowCount() {
return rowCount;
}
public void setRowCount(int rowCount) {
this.rowCount = rowCount;
}
public int getCellMargin() {
return cellMarginPx;
}
public void setCellMargin(int marginInDp) {
this.cellMarginPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginInDp, getContext().getResources().getDisplayMetrics());
}
public void setCellMarginRes(int marginRes) {
this.cellMarginPx = getContext().getResources().getDimensionPixelSize(marginRes);
}
private boolean hasUnlimitedRows() {
return rowCount <= 0;
}
public static class LayoutParams extends ViewGroup.LayoutParams {
public final int colIndex;
public final int colSpan;
public final int rowIndex;
public final int rowSpan;
public LayoutParams(int colIndex, int colSpan, int rowIndex, int rowSpan) {
super(MATCH_PARENT, MATCH_PARENT);
this.colIndex = colIndex;
this.colSpan = colSpan;
this.rowIndex = rowIndex;
this.rowSpan = rowSpan;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment