我正在创建带有简单图块的等轴测图,并扩展了RelativeLayout以创建可容纳这些图块的布局。的确,只要我的方位与将磁贴写入XML文件的顺序相匹配,就可以按原样使用RelativeLayout可以正常工作;我覆盖的全部是构造函数,在这里我只调用supersetChildrenDrawingOrderEnabled(true);并设置一些变量(网格的高度和宽度),然后设置getChildDrawingOrder本身。

我的getChildDrawingOrder代码会找出给定子项的新索引,并将子项中的字符串设置为i->i',其中i是原始索引,而i'是新索引。我正在使用它进行测试; children 将在自己的坐标上绘制此字符串。

不幸的是,它不能正常工作,或者说它不稳定。在我的测试案例中的9个磁贴中,似乎3个根本没有调用getChildDrawingOrder:我上面提到的字符串是null。在其余的中,尽管传递了正确的索引,但至少有一个顺序困惑。

这是一张图片(按TOP方向):

注意(0,2),(1,2)和(2,1)都列为NULL,因此getChildDrawingOrder似乎从未被调用过。另请注意,即使(1,0)绘制在(1,1)的顶部,即使其i(3)和i'(1)都小于(1,1)的(分别为4和4)。

这是getChildDrawingOrder的代码:

@Override
protected int getChildDrawingOrder(int childCount, int i)
{
    TileView ch = (TileView)getChildAt(i);
    ch.order = "Called"; // this string is drawn on my children
    int gx, gy; // the "true" x,y for the current rotation,
                // where 0,0 is the top corner
    switch (rotation)
    {
    case TOP:
        gx = ch.x();
        gy = ch.y();
        break;
    case LEFT:
        gx = (width()-1-ch.x());
        gy = ch.y();
        break;
    case RIGHT:
        gx = ch.x();
        gy = (length()-1-ch.y());
        break;
    case BOTTOM:
        gx = (width()-1-ch.x());
        gy = (length()-1-ch.y());
        break;
    default:
        gx = ch.x();
        gy = ch.y();
    }
    int row = gx+gy; // current row
    if ( row == 0 ) // row 0 is always just the top corner and 0
    {
        ch.order = new String(i+"->0"); // string set to i->i'
        return 0;
    }
    else
    {
        int mx = width()-1, // maximum x value
            my = length()-1, // maximum y value
            mrow = mx+my, // maximum row
            min = Math.min(mx, my), // minor axis length
            maj = Math.max(mx, my), // major axis length
            retn; // for storing the return value
        // inside the top corner
        if ( row <= min )
        {
            // Gauss's formula to get number of cells in previous rows
            // plus the number for which cell in this row this is.
            retn = row*(row+1)/2+gy;
        }
        // in the middle
        else if ( row <= maj )
        {
            // Gauss's formula to get number of cells in top corner
            // plus the number of cells in previous rows of the middle section
            // plus the number for which cell in this row this is.
            retn = min*(min+1)/2+min*(row-min)+gy;
        }
        // bottom corner
        else
        {
            retn = (min+1)*(min+2)/2 // cells in the top corner
                 + min*(maj-min) // cells in the middle
                 + (mrow-maj)*(mrow-maj+1)/2 // total cells in bottom triangle
                 - (mrow-row+1)*(mrow-row+2)/2 // less cells after this one
                 + gy // which cell in this row
                 - (row-maj) // to account for gy not starting at zero
                 ;
        }
        ch.order = new String(i+"->"+retn); // string set to i->i'
        return retn;
    }
}

任何人都可以对发生的事情有所了解吗?为什么不为这三个图块调用getChildDrawingOrder?即使调用了getChildDrawingOrder,为什么仍以错误的顺序绘制(1,0)?

最佳答案

好的,可以通过查看Android源代码来弄清楚。我有getChildDrawingOrder的映射:传递的i是“我应该画哪个 child ?”不是“我什么时候画 child 我?”之所以使用NULL,是因为这些子项是在传递自己的i之前绘制的。

我更改了代码以找出onMeasure传递期间所有子代的顺序,将其保存在SparseIntArray中,然后从getChildDrawingOrder中返回。这有效。

顺便说一下,对getChildDrawingOrder函数中的索引进行反向计算是一个坏主意,除非您要依赖于声明子级的顺序。因为如果您不依赖该顺序,则必须遍历子代列表以找到具有适当x和y值的子代,这意味着您必须遍历每个子代的子代列表。那是一个O(n²)运算(读:相当低效)。数学也相当复杂。

07-28 03:53