setMeasuredDimension()中的大小不正确还是大小计算不正确?

时间:2016-01-15 16:09:45

标签: java android android-layout

我需要类似网格布局的东西,但有自己的元素定位逻辑。我扩展了Frame Layout,并编写了以下逻辑:

super.onMeasure(widthMeasureSpec,heightMeasureSpec);
int childCount = getChildCount();
    if (childCount==0) return;
    int cellSize= 0;
    for (int i=0;i<getChildCount();i++) {
        cellSize = Math.max(cellSize, getChildAt(i).getMeasuredHeight());
    }
    cellSize= Math.min(getMeasuredHeight()/rowCount,cellSize);
    if (autoColumnCount&&cellSize>0) {
        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        Point displaySize = new Point();
        display.getSize(displaySize);
        int screenWidth = displaySize.x;
        columnCount = Math.max(screenWidth/cellSize - autoColumnOffset,1);
    }
    cellSize = cellSize - cellPadding*2;
    ArrayList<ArrayList<Integer>> sortedIndexes = new ArrayList<>();
    int currentIndex=0;
    while (true) {
        if (currentIndex>=childCount) break;
        ArrayList<Integer> indexes = new ArrayList<>();
        indexes.add(currentIndex);
        for (int y=1;y<rowCount;y++) {
            int index = currentIndex + (y*columnCount);
            if (index<childCount)
                indexes.add(index);
            else
                break;
        }
        sortedIndexes.add(indexes);
        currentIndex++;
        if (currentIndex%columnCount==0) {
            currentIndex = (currentIndex-columnCount)+(rowCount*columnCount);
        }
    }
    int maxRows = 1;
    for (int i=0;i<rowCount;i++) {
        for (int y=0;y<sortedIndexes.size();y++) {
            ArrayList<Integer> indexes = sortedIndexes.get(y);
            if (i<indexes.size()) {
                maxRows = Math.max(maxRows,i+1);
                View v = getChildAt(indexes.get(i));
                int newX = y*cellSize+(y+1)*cellPadding+y*cellPadding;
                int newY = i*cellSize+(i+1)*cellPadding+i*cellPadding;
                int measureSpecWidth = MeasureSpec.makeMeasureSpec(Math.min(cellSize,v.getMeasuredWidth()), MeasureSpec.AT_MOST);
                int measureSpecHeight = MeasureSpec.makeMeasureSpec(Math.min(cellSize,v.getMeasuredHeight()), MeasureSpec.AT_MOST);
                v.measure(measureSpecWidth, measureSpecHeight);
                centerViewInBounds(v, newX, newY, newX + cellSize, newY + cellSize);
            }
        }
    }
    final int neededHeight = maxRows*cellSize+maxRows*cellPadding*2;
    final int neededWidth = sortedIndexes.size()*cellSize+sortedIndexes.size()*cellPadding*2;
    MyLog.print("asd", "Column count: " + sortedIndexes.size() + "\nCell size (with padding): " + (cellSize + cellPadding * 2) + "\nWidth: " + neededWidth);
    setMeasuredDimension(neededWidth, neededHeight);

单元格应为方形,布局只能在宽度上增长并存储在Horizo​​ntalScrollView中。问题是函数setMeasuredDimension工作不正确或我收到的大小是错误的(虽然,在我看来,一切都应该工作正常):有了这个逻辑我接下来的事情: Screenshot

问题出在哪里?提前谢谢。

1 个答案:

答案 0 :(得分:0)

好的,我读了所有关于&#34; android如何绘制视图&#34;在互联网上找到了更多的解释,我写了下一个逻辑:

    private void sortChildren() {
    int childCount = getChildCount();
    sortedIndexes.clear();
    int currentIndex=0;
    while (true) {
        if (currentIndex>=childCount) break;
        ArrayList<Integer> indexes = new ArrayList<>();
        indexes.add(currentIndex);
        for (int y=1;y<rowCount;y++) {
            int index = currentIndex + (y*columnCount);
            if (index<childCount) {
                indexes.add(index);
                maxVisibleRows = Math.max(indexes.size(), maxVisibleRows);
            } else break;
        }
        sortedIndexes.add(indexes);
        currentIndex++;
        if (currentIndex%columnCount==0) {
            currentIndex = (currentIndex-columnCount)+(rowCount*columnCount);
        }
    }
    maxVisibleColumns = sortedIndexes.size();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int width = 0;
    int height = 0;

    sortChildren();

    switch (heightMode) {
        case MeasureSpec.EXACTLY:
            height = MeasureSpec.getSize(heightMeasureSpec);
            cellSize = height/rowCount;
            break;
        case MeasureSpec.AT_MOST:
            height = MeasureSpec.getSize(heightMeasureSpec);
            cellSize = height/rowCount;
            height = Math.min(height,cellSize* maxVisibleRows);
            break;
        case MeasureSpec.UNSPECIFIED:
            cellSize = defaultCellSize;
            height = defaultCellSize* maxVisibleRows;
            break;
    }

    switch (widthMode) {
        case MeasureSpec.EXACTLY:
            width = MeasureSpec.getSize(widthMeasureSpec);
            break;
        case MeasureSpec.AT_MOST:
            width = Math.min(MeasureSpec.getSize(widthMeasureSpec),maxVisibleColumns*cellSize);
            break;
        case MeasureSpec.UNSPECIFIED:
            width = maxVisibleColumns*cellSize;
            break;
    }

    int childCount = getChildCount();
    for (int i=0;i<childCount;i++) {
        View view = getChildAt(i);
        int cellMeasureSpec = MeasureSpec.makeMeasureSpec(cellSize-cellPadding*2,MeasureSpec.EXACTLY);
        view.measure(cellMeasureSpec,cellMeasureSpec);
    }

    setMeasuredDimension(width,height);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    for (int i=0;i<rowCount;i++) {
        for (int y = 0; y < sortedIndexes.size(); y++) {
            ArrayList<Integer> indexes = sortedIndexes.get(y);
            if (i < indexes.size()) {
                maxVisibleRows = Math.max(maxVisibleRows, i + 1);
                View v = getChildAt(indexes.get(i));
                if (v == null) continue;
                int yOffset = (int)((1.0f*rowCount-maxVisibleRows)/2*cellSize);
                int newX = y * cellSize;
                int newY = i * cellSize + yOffset;
                v.layout(newX + cellPadding, newY + cellPadding, newX + cellSize - cellPadding, newY + cellSize - cellPadding);
            }
        }
    }
}

现在它按预期工作。