自定义视图组中的子视图不遵循边界

时间:2013-04-02 16:02:48

标签: java android android-layout

我正在创建一个自定义布局(viewgroup子类),它将自身划分为单元格,然后根据单元格位置和单元格宽度/高度定位子布局。

将其视为小部件的组织方式。

我添加了一堆具有不同背景颜色的框架布局,它们似乎正确定位。然而,当我放入textview时,它会在垂直方向上扩展得更好,并且水平地保持固定宽度。这个职位可以正常运作。

代码:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

public class DynamicLayout extends ViewGroup {

int numCellsX = 6, numCellsY = 8;
int cellSize;

int blockMap[];

public DynamicLayout(Context context) {
    super(context);

    init();
}

public DynamicLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public DynamicLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

private void init()
{
    blockMap = new int[numCellsX * numCellsY];
    clearBlockMap();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    cellSize = getMeasuredWidth() / numCellsX;

    int specWidth = MeasureSpec.getSize(widthMeasureSpec);
    int specHeight = MeasureSpec.getSize(heightMeasureSpec);

    this.setMeasuredDimension(specWidth, specHeight);

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    if (getChildCount() > 0) {
        int wspec = MeasureSpec.makeMeasureSpec(getMeasuredWidth()
                / getChildCount(), MeasureSpec.EXACTLY);
        int hspec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
                MeasureSpec.EXACTLY);
        for (int i = 0; i < getChildCount(); i++) {
            View v = getChildAt(i);
            v.measure(wspec, hspec);
        }
    }
    Log.i("DYNA", "Measured");
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    Log.i("DYNA", "On Layout");

    clearBlockMap();

    for (int i = 0; i < getChildCount(); i++) {
        View v = getChildAt(i);

        if (v instanceof DynaServiceView) {
            DynaServiceView serviceView = (DynaServiceView) v;

            if (serviceView.getVisibility() == GONE) 
                continue;


            int x = serviceView.getXPos();
            int y = serviceView.getYPos();
            int width = serviceView.getXCells();
            int height = serviceView.getYCells();

            //Is the thing too big?
            if (width > numCellsX)
            {
                Log.i("DYNA", "Warning, service too big, shrinking to size");
                width = numCellsX;
                serviceView.setWidth(width);
            }

            //Is there space?
            if (checkBlockMap(x, y, width, height))
            {
                Log.i("DYNA", "Found collision at child " + i +", resolving...");
                //Find somewhere to put this
                boolean foundSpot = false;
                for (int j = y; j <= numCellsY - height; j++)
                {
                    for (int k = x; k <= numCellsX - width; k++)
                    {
                        if (!checkBlockMap(k, j, width, height))
                        {
                            x = k;
                            y = j;                              
                            foundSpot = true;
                            break;
                        }
                    }

                    if (foundSpot)
                        break;
                }

                if (!foundSpot)                 
                    Log.i("DYNA", "No spot for child at: " + i + ", skipping!");
                else
                    Log.i("DYNA", "Resolved! New X/Y: " + x + ", " + y);
            }

            setBlockMap(x, y, width, height);

            //Has spot now, set layout
            serviceView.layout(l + (x * cellSize), t + (y * cellSize), (x * cellSize)
                    + (width * cellSize), (y * cellSize)
                    + (height * cellSize));
        }

    }       
}

private boolean checkBlockMap(int x, int y, int width, int height)
{
    for (int  j= y; j < y + height; j++)
    {
        for (int k = x; k < x + width; k++)                     
            if (blockMap[(j * numCellsX) + k] == 1)
                return true;
    }
    return false;
}

private void setBlockMap(int x, int y, int width, int height)
{
    for (int  j= y; j < y + height; j++)
    {
        for (int k = x; k < x + width; k++)                     
            blockMap[(j * numCellsX) + k] = 1;
    }
}

private void clearBlockMap()
{
    for (int i = 0; i < blockMap.length;i++)
        blockMap[i] = 0;
}
}

这是解释问题的图片。在右侧,您可以看到布局的边框正确排列,但是在左侧显然,子文本视图没有跟随它。

enter image description here

1 个答案:

答案 0 :(得分:1)

发现问题.... onMeasure设置不正确。愚蠢的错误。