6

単純なタイルを使用してアイソメ マップをRelativeLayout作成しており、これらのタイルを保持するレイアウトを作成するために拡張しました。実際、RelativeLayout向きがタイルが XML ファイルに書き込まれた順序と一致している限り、そのままを使用するだけで問題なく機能しました。上書きしたのはコンストラクターだけです。ここでは、いくつかの変数 (グリッドの高さと幅) を設定するだけでなくsuper、コンストラクター自体を呼び出すだけです。setChildrenDrawingOrderEnabled(true);getChildDrawingOrder

の私のコードはgetChildDrawingOrder、指定された子の新しいインデックスを計算し、子の文字列を に設定しますi->i'。ここiで、 は元のインデックスで、i'は新しいインデックスです。これをテストに使用しています。子は、座標とともにこの文字列を自分自身に描画するように設定されています。

残念ながら、正しく動作しないか、不安定に動作します。私のテスト ケースの 9 つのタイルのうち、3 つがまったく呼び出されていないようです。getChildDrawingOrder上記の文字列はnull. 残りのうち、正しいインデックスが渡されたにもかかわらず、少なくとも 1 つが順不同で描画されています。

ここに写真があります(TOPオリエンテーションで):

getChildDrawingOrder 失敗のイメージ

(0,2)、(1,2)、および (2,1) はすべて としてリストされているNULLため、getChildDrawingOrder呼び出されていないように見えることに注意してください。iまた、 (3) とi'(1) の両方が (1,1) の (それぞれ 4 と 4) より小さいにもかかわらず、(1,0) は (1,1) の上に描画されることに注意してください。

からのコードは次の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これらの 3 つのタイルが呼び出されないのはなぜですか? (1,0)getChildDrawingOrder 呼び出されているにもかかわらず、なぜ間違った順序で描画されるのですか?

4

2 に答える 2

12

OK、Androidのソースコードを見て理解しました。私は次のマッピングを持っていましたgetChildDrawingOrder:渡されたのは「iはどの子を描くべきですか?」です。「いつ子供を描くべきか」ではありません。sの理由は、それらの子供たちが彼ら自身が渡される前に引き寄せられていたからです。NULLi

パス中のすべての子の順序を把握するようにコードを変更し、onMeasureそれをに保存しSparseIntArrayてから、から返しましたgetChildDrawingOrder。これは機能します。

getChildDrawingOrderちなみに、子が宣言されている順序に依存したい場合を除いて、関数内のインデックスを逆算することはお勧めできません。その順序に依存しない場合は、子のリストを調べて、適切なx値とy値を持つ子を見つける必要があります。つまり、各子の子のリストを調べる必要があります。これはO(n²)操作です(読み取り:かなり非効率的です)。数学もかなり複雑です。

于 2013-01-24T20:43:48.630 に答える