Last active
February 21, 2017 09:55
-
-
Save Sirelon/3d91eed43d9c5a4b0d327e85dc439c65 to your computer and use it in GitHub Desktop.
FlexableGridViewGroup.
This file contains hidden or 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
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