带有 ColumnSpec 的 Gridlayout 导致布局使用全屏宽度
Gridlayout with ColumnSpec causing layout to use full screen width
我正在使用具有两列的 GridLayout,并且我想为其中的一行插入一个分隔条。当我插入栏时,布局变为全屏宽度。没有栏,它的行为与我预期的一样 WRAP_CONTENT.
我动态创建布局及其所有内容,而不是 XML。以下是要点:
private class ContentView extends GridLayout
{
ContentView (Context context)
{
super (context);
setColumnCount (2);
}
// adds "child" to the next cell in the layout
public void addView (View child, ViewGroup.LayoutParams params)
{
super.addView (child, params);
//... other code not shown ...
}
public void addDivider()
{
int padding = (int) getResources().getDimension (R.dimen.normal_text_margin);
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.width = LayoutParams.WRAP_CONTENT;
params.height = (int) getResources().getDimension (R.dimen.divider_bar_height);
params.columnSpec = GridLayout.spec (0,2); // add to pair of columns
View v = new View (getContext());
v.setBackgroundColor (Color.BLACK);
v.setPadding (padding, 0, padding, 0);
v.setLayoutParams (params);
super.addView (v, params);
}
}
这由以下调用,其中 "v" 是 GridLayout:
public View setContentView (ViewGroup v)
{
contentView = v;
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
borderView.addView (contentView, params);
return contentView;
}
如果我注释掉 addDivider 代码,布局就会变窄。当我启用代码时,布局是全屏宽度。我需要设置什么不同的属性才能使栏不增加布局宽度?
我没有找到使用 GridLayout 完成这项工作的方法(尽管我不得不承认我没有花时间检查源代码)。相反,我写了一些非常简单的东西来做我需要的。
如果其他人发现此代码有用,请看这里。它允许多列和多行,其中每列的宽度由最宽成员的宽度定义。同样对于行高。我添加了一个 api 用于插入行分隔符(只允许一个分隔符,但你可以扩展它以具有多个分隔符)。
还缺少每个单元格的布局参数,因为我现在不需要它。它左对齐内容并将其垂直居中。还缺少单元格填充。就像我说的,一个简单的实现。但容易增强。
public class SimpleGridLayout extends ViewGroup
{
private Paint barPaint;
int cols = 0;
int[] colWidths = null;
int[] rowHeights = null;
int dividerRow = -1; // only allow one divider row, keep implementation simple
int dividerHeight = 0; // pixels
int dividerMargin = 0; // pixels
int yDivider = 0;
//-----------------------------------------------------------------------------
public SimpleGridLayout (Context context)
{
super (context);
barPaint = new Paint(); // for painting insertion line
dividerHeight = (int) getResources().getDimension(R.dimen.divider_bar_height);
dividerMargin = (int) getResources().getDimension(R.dimen.divider_bar_margin);
setWillNotDraw (false);
}
//-----------------------------------------------------------------------------
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
// clear column widths, create height array
for (int i = 0; i < cols; i++)
colWidths[i] = 0;
rowHeights = new int [(getChildCount() + cols - 1) / cols]; // account for partial row
// determine column widths, working from left to right
int widthAvailable = MeasureSpec.getSize (widthMeasureSpec);
for (int iCol = 0; iCol < cols; iCol++)
{
// visit each row
for (int i = iCol, iRow = 0, limit = getChildCount(); i < limit; i += cols, iRow++)
{
View child = getChildAt(i);
int itemWidthSpec = MeasureSpec.makeMeasureSpec (widthAvailable, MeasureSpec.AT_MOST);
int itemHeightSpec = MeasureSpec.makeMeasureSpec (0, MeasureSpec.UNSPECIFIED);
child.measure (itemWidthSpec, itemHeightSpec);
colWidths [iCol] = Math.max (colWidths [iCol], child.getMeasuredWidth());
rowHeights [iRow] = Math.max (rowHeights [iRow], child.getMeasuredHeight());
}
widthAvailable -= colWidths [iCol];
}
// get total width
int width = 0;
for (int i = 0; i < cols; i++)
width += colWidths [i];
// get total height
int height = 0;
for (int i = 0; i < rowHeights.length; i++)
height += rowHeights [i];
if (dividerRow != -1)
height += dividerHeight;
setMeasuredDimension (width, height);
}
//-----------------------------------------------------------------------------
@Override
protected void onLayout (boolean changed, int l, int t, int r, int b)
{
// layout each column, working from left to right
int xCol = 0;
for (int iCol = 0; iCol < cols; iCol++)
{
int yRow = 0;
// visit each row
for (int i = iCol, iRow = 0, limit = getChildCount(); i < limit; i += cols, iRow++)
{
View child = getChildAt(i);
if (iRow == dividerRow)
{
yDivider = yRow;
yRow += dividerHeight;
}
// left justify
int left = xCol;
// center vertically
int dyRow = rowHeights [iRow];
int top = yRow + (dyRow - child.getMeasuredHeight()) / 2;
int right = left + child.getMeasuredWidth();
int bottom = top + child.getMeasuredHeight();
child.layout (left, top, right, bottom);
yRow += rowHeights [iRow];
}
xCol += colWidths [iCol];
}
}
//-----------------------------------------------------------------------------
@Override
protected void onDraw (Canvas canvas)
{
barPaint.setColor (getResources().getColor (R.color.divider_bar));
canvas.drawRect (dividerMargin,
yDivider,
getWidth() - 2*dividerMargin,
yDivider + dividerHeight,
barPaint);
}
//-----------------------------------------------------------------------------
@Override
public void addView (View v, LayoutParams params)
{
super.addView (v, params);
rowHeights = null;
}
//-----------------------------------------------------------------------------
public void addDivider ()
{
rowHeights = null;
dividerRow = (getChildCount() + 1) / cols;
}
//-----------------------------------------------------------------------------
public void setColumnCount (int cols)
{
this.cols = cols;
colWidths = new int[cols];
}
}
我正在使用具有两列的 GridLayout,并且我想为其中的一行插入一个分隔条。当我插入栏时,布局变为全屏宽度。没有栏,它的行为与我预期的一样 WRAP_CONTENT.
我动态创建布局及其所有内容,而不是 XML。以下是要点:
private class ContentView extends GridLayout
{
ContentView (Context context)
{
super (context);
setColumnCount (2);
}
// adds "child" to the next cell in the layout
public void addView (View child, ViewGroup.LayoutParams params)
{
super.addView (child, params);
//... other code not shown ...
}
public void addDivider()
{
int padding = (int) getResources().getDimension (R.dimen.normal_text_margin);
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.width = LayoutParams.WRAP_CONTENT;
params.height = (int) getResources().getDimension (R.dimen.divider_bar_height);
params.columnSpec = GridLayout.spec (0,2); // add to pair of columns
View v = new View (getContext());
v.setBackgroundColor (Color.BLACK);
v.setPadding (padding, 0, padding, 0);
v.setLayoutParams (params);
super.addView (v, params);
}
}
这由以下调用,其中 "v" 是 GridLayout:
public View setContentView (ViewGroup v)
{
contentView = v;
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
borderView.addView (contentView, params);
return contentView;
}
如果我注释掉 addDivider 代码,布局就会变窄。当我启用代码时,布局是全屏宽度。我需要设置什么不同的属性才能使栏不增加布局宽度?
我没有找到使用 GridLayout 完成这项工作的方法(尽管我不得不承认我没有花时间检查源代码)。相反,我写了一些非常简单的东西来做我需要的。
如果其他人发现此代码有用,请看这里。它允许多列和多行,其中每列的宽度由最宽成员的宽度定义。同样对于行高。我添加了一个 api 用于插入行分隔符(只允许一个分隔符,但你可以扩展它以具有多个分隔符)。
还缺少每个单元格的布局参数,因为我现在不需要它。它左对齐内容并将其垂直居中。还缺少单元格填充。就像我说的,一个简单的实现。但容易增强。
public class SimpleGridLayout extends ViewGroup
{
private Paint barPaint;
int cols = 0;
int[] colWidths = null;
int[] rowHeights = null;
int dividerRow = -1; // only allow one divider row, keep implementation simple
int dividerHeight = 0; // pixels
int dividerMargin = 0; // pixels
int yDivider = 0;
//-----------------------------------------------------------------------------
public SimpleGridLayout (Context context)
{
super (context);
barPaint = new Paint(); // for painting insertion line
dividerHeight = (int) getResources().getDimension(R.dimen.divider_bar_height);
dividerMargin = (int) getResources().getDimension(R.dimen.divider_bar_margin);
setWillNotDraw (false);
}
//-----------------------------------------------------------------------------
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
// clear column widths, create height array
for (int i = 0; i < cols; i++)
colWidths[i] = 0;
rowHeights = new int [(getChildCount() + cols - 1) / cols]; // account for partial row
// determine column widths, working from left to right
int widthAvailable = MeasureSpec.getSize (widthMeasureSpec);
for (int iCol = 0; iCol < cols; iCol++)
{
// visit each row
for (int i = iCol, iRow = 0, limit = getChildCount(); i < limit; i += cols, iRow++)
{
View child = getChildAt(i);
int itemWidthSpec = MeasureSpec.makeMeasureSpec (widthAvailable, MeasureSpec.AT_MOST);
int itemHeightSpec = MeasureSpec.makeMeasureSpec (0, MeasureSpec.UNSPECIFIED);
child.measure (itemWidthSpec, itemHeightSpec);
colWidths [iCol] = Math.max (colWidths [iCol], child.getMeasuredWidth());
rowHeights [iRow] = Math.max (rowHeights [iRow], child.getMeasuredHeight());
}
widthAvailable -= colWidths [iCol];
}
// get total width
int width = 0;
for (int i = 0; i < cols; i++)
width += colWidths [i];
// get total height
int height = 0;
for (int i = 0; i < rowHeights.length; i++)
height += rowHeights [i];
if (dividerRow != -1)
height += dividerHeight;
setMeasuredDimension (width, height);
}
//-----------------------------------------------------------------------------
@Override
protected void onLayout (boolean changed, int l, int t, int r, int b)
{
// layout each column, working from left to right
int xCol = 0;
for (int iCol = 0; iCol < cols; iCol++)
{
int yRow = 0;
// visit each row
for (int i = iCol, iRow = 0, limit = getChildCount(); i < limit; i += cols, iRow++)
{
View child = getChildAt(i);
if (iRow == dividerRow)
{
yDivider = yRow;
yRow += dividerHeight;
}
// left justify
int left = xCol;
// center vertically
int dyRow = rowHeights [iRow];
int top = yRow + (dyRow - child.getMeasuredHeight()) / 2;
int right = left + child.getMeasuredWidth();
int bottom = top + child.getMeasuredHeight();
child.layout (left, top, right, bottom);
yRow += rowHeights [iRow];
}
xCol += colWidths [iCol];
}
}
//-----------------------------------------------------------------------------
@Override
protected void onDraw (Canvas canvas)
{
barPaint.setColor (getResources().getColor (R.color.divider_bar));
canvas.drawRect (dividerMargin,
yDivider,
getWidth() - 2*dividerMargin,
yDivider + dividerHeight,
barPaint);
}
//-----------------------------------------------------------------------------
@Override
public void addView (View v, LayoutParams params)
{
super.addView (v, params);
rowHeights = null;
}
//-----------------------------------------------------------------------------
public void addDivider ()
{
rowHeights = null;
dividerRow = (getChildCount() + 1) / cols;
}
//-----------------------------------------------------------------------------
public void setColumnCount (int cols)
{
this.cols = cols;
colWidths = new int[cols];
}
}