Last active
December 14, 2015 17:48
-
-
Save DayS/ea0c22b60dd263443316 to your computer and use it in GitHub Desktop.
Display views in a grid with customizable cells sizes an position
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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