带有 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];
  }
}