Skip to content

Instantly share code, notes, and snippets.

@Sirelon
Last active February 21, 2017 09:55
Show Gist options
  • Save Sirelon/3d91eed43d9c5a4b0d327e85dc439c65 to your computer and use it in GitHub Desktop.
Save Sirelon/3d91eed43d9c5a4b0d327e85dc439c65 to your computer and use it in GitHub Desktop.
FlexableGridViewGroup.
package com.sirelon;
import android.content.Context;
import android.support.annotation.DimenRes;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* @author sirelon
* @since 17.02.17 on 14:54.
*/
public class FlexebleGridViewGroup extends ViewGroup {
private int itemPerRow = 2;
public FlexebleGridViewGroup(Context context) {
super(context);
}
public FlexebleGridViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlexebleGridViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FlexebleGridViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int childWidth = width / itemPerRow;
// Measurement will ultimately be computing these values.
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
// Iterate through all children, measuring them and computing our dimensions
// from their size.
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
// Measure the child.
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
// Update our size information based on the layout params. Children
// that asked to be positioned on the left or right go in those gutters.
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
maxWidth = Math.max(maxWidth, child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
maxHeight = Math.max(maxHeight, child.getMeasuredHeight() + lp.bottomMargin + lp.topMargin);
childState = combineMeasuredStates(childState, child.getMeasuredState());
}
}
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
if (count >= itemPerRow) {
double a = count / (double) itemPerRow;
long round = Math.round(a);
maxHeight *= round;
}
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
// Report our final dimensions.
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec, childState));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int count = getChildCount();
int lastChildsToAlign = count - (count % itemPerRow);
int offsetTop = 0, lines = 0, offsetLeft;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE)
continue;
final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();
if ((i % itemPerRow) == 0) {
// The next line
offsetLeft = 0;
offsetTop = height * lines;
lines++;
} else {
offsetLeft = width * (i % itemPerRow);
}
if (i >= lastChildsToAlign) {
// All items munis items which needed to align
int offset = itemPerRow - (count - lastChildsToAlign);
offsetLeft += (width / 2) * offset;
}
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childBottom = offsetTop + height - lp.bottomMargin;
int childTop = offsetTop + lp.topMargin;
int childLeft = offsetLeft + lp.leftMargin;
int childRight = offsetLeft + width + lp.rightMargin;
// Place the child.
child.layout(childLeft, childTop, childRight, childBottom);
}
}
public void setItemPerRow(int itemPerRow) {
this.itemPerRow = itemPerRow;
requestLayout();
}
public void setSpaceBetweenItems(@DimenRes int dimenRes) {
final int spaceSize = (int) getContext().getResources().getDimension(dimenRes);
final int childCount = getChildCount();
int lines = (int) Math.round(childCount / (double) itemPerRow);
for (int i = 0; i < childCount; i++) {
int flag = (i + 1) % itemPerRow;
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
if (lines > 1) {
lp.bottomMargin = spaceSize;
} else if (childCount - i < itemPerRow) {
lp.topMargin = spaceSize;
}
if (flag == 1) {
lp.rightMargin = spaceSize;
} else if (flag == 0) {
lp.leftMargin = spaceSize;
lines--;
} else {
lp.leftMargin = spaceSize;
lp.rightMargin = spaceSize;
}
child.setLayoutParams(lp);
}
}
@Override
public MarginLayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected MarginLayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
@Override
protected ViewGroup.MarginLayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new MarginLayoutParams(p);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof MarginLayoutParams;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment