Ich habe einige der obigen Ausführungen angepasst und ein fließendes Layout implementiert, das alle untergeordneten Ansichten, horizontal und vertikal, zentriert. Es passt zu meinen Bedürfnissen.
public class CenteredFlowLayout extends ViewGroup {
private int lineHeight;
private int centricHeightPadding;
private final int halfGap;
public static final List<View> LINE_CHILDREN = new ArrayList<View>();
public static class LayoutParams extends ViewGroup.LayoutParams {
public final int horizontalSpacing;
public final int verticalSpacing;
public LayoutParams(int horizontalSpacing, int verticalSpacing) {
super(0, 0);
this.horizontalSpacing = horizontalSpacing;
this.verticalSpacing = verticalSpacing;
}
}
public CenteredFlowLayout(Context context) {
super(context);
halfGap = getResources().getDimensionPixelSize(R.dimen.half_gap);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
final int maxHeight = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
final int count = getChildCount();
int lineHeight = 0;
int xAxis = getPaddingLeft();
int yAxis = getPaddingTop();
int childHeightMeasureSpec;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
} else {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final CentricFlowLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
final int childMeasuredWidth = child.getMeasuredWidth();
lineHeight = Math.max(lineHeight, child.getMeasuredHeight() + lp.verticalSpacing);
if (xAxis + childMeasuredWidth > width) {
xAxis = getPaddingLeft();
yAxis += lineHeight;
} else if (i + 1 == count) {
yAxis += lineHeight;
}
xAxis += childMeasuredWidth + lp.horizontalSpacing;
}
}
this.lineHeight = lineHeight;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
height = yAxis + lineHeight;
} else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
if (yAxis + lineHeight < height) {
height = yAxis + lineHeight;
}
}
if (maxHeight == 0) {
maxHeight = height + getPaddingTop();
}
centricHeightPadding = (maxHeight - height) / 2;
setMeasuredDimension(width, disableCenterVertical ? height + getPaddingTop() : maxHeight);
}
@Override
protected CentricFlowLayout.LayoutParams generateDefaultLayoutParams() {
return new CentricFlowLayout.LayoutParams(halfGap, halfGap);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
if (p instanceof LayoutParams) {
return true;
}
return false;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
final int width = r - l;
int yAxis = centricHeightPadding + getPaddingTop() + getPaddingBottom();
View child;
int measuredWidth;
int lineWidth = getPaddingLeft() + getPaddingRight();
CentricFlowLayout.LayoutParams lp;
int offset;
LINE_CHILDREN.clear();
for (int i = 0; i < count; i++) {
child = getChildAt(i);
lp = (LayoutParams) child.getLayoutParams();
if (GONE != child.getVisibility()) {
measuredWidth = child.getMeasuredWidth();
if (lineWidth + measuredWidth + lp.horizontalSpacing > width) {
offset = (width - lineWidth) / 2;
layoutHorizontalCentricLine(LINE_CHILDREN, offset, yAxis);
lineWidth = getPaddingLeft() + getPaddingRight() + measuredWidth + lp.horizontalSpacing;
yAxis += lineHeight;
LINE_CHILDREN.clear();
LINE_CHILDREN.add(child);
} else {
lineWidth += measuredWidth + lp.horizontalSpacing;
LINE_CHILDREN.add(child);
}
}
}
offset = (width - lineWidth) / 2;
layoutHorizontalCentricLine(LINE_CHILDREN, offset, yAxis);
}
private void layoutHorizontalCentricLine(final List<View> children, final int offset, final int yAxis) {
int xAxis = getPaddingLeft() + getPaddingRight() + offset;
for (View child : children) {
final int measuredWidth = child.getMeasuredWidth();
final int measuredHeight = child.getMeasuredHeight();
final CentricFlowLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(xAxis, yAxis, xAxis + measuredWidth, yAxis + measuredHeight);
xAxis += measuredWidth + lp.horizontalSpacing;
}
}
}