2013-01-24 3 views
5

私はシンプルなタイルでアイソメトリックマップを作成しています。これらのタイルを保持するレイアウトを作成するには、をRelativeLayoutに拡張しました。実際には、ちょうどRelativeLayoutをそのまま使っても、私の向きがXMLファイルに書き込まれた順番と一致していれば問題ありません。すべて’が上書きされたコンストラクタは、supersetChildrenDrawingOrderEnabled(true);を呼び出し、いくつかの変数(グリッドの高さと幅)を設定してからgetChildDrawingOrderと呼ぶだけです。getChildDrawingOrderが不当に呼び出されましたか?

与えられた子供のための新たな指標うちgetChildDrawingOrder数値のための私のコードでは、ともiは、元の索引とi'が新しいインデックスであるi->i'の子で文字列を設定します。私は’ mこれをテストに使用します。子どもたちは座標と一緒にこの文字列を描画するように設定されています。

残念ながら、正しく動作しないか、むしろ不安定に動作します。私のテストケースの9つのタイルのうち、’の3つのドンは、まったくgetChildDrawingOrderというように見えます。上記の文字列は、nullです。残りのうち、正しいインデックスが渡されたにもかかわらず、少なくとも1つは順序が乱れています。ここ

’ SA(TOP向きの)画像(0,2)、(1,2)、および(2,1)は全てNULLとして表示されていること

Image of getChildDrawingOrder failure

お知らせそのためにgetChildDrawingOrderが呼び出されたことはありません。また、i(3)とi'(1)の両方が(1,1)’(4と4)未満であっても、(1,1)の上に(1,0)が描画されていることにも注意してください。

ここ’の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; 
    } 
} 

誰もが’ sが起こって何にいくつかの光を当てることができますか?なぜこれらの3つのタイルにisn ’ t getChildDrawingOrderが呼び出されていますか? getChildDrawingOrderであるにもかかわらず、(1,0)が間違った順序で描かれているのはなぜですか?

答えて

10

いいえ、Androidソースコードを見て分かりました。私はgetChildDrawingOrderのマッピングを持っていました:iが渡されたのは“です。どの子を描くべきですかi th? ”「いつ私は子供を描くべきですか?」 NULLの理由は、自分のiが渡される前にその子供たちが描かれていたからです。

onMeasureのパスの間にすべての子供の注文を把握するようにコードを変更し、SparseIntArrayに保存して、それをちょうどgetChildDrawingOrderから返しました。これは機能します。

getChildDrawingOrder関数のインデックスを逆算する方法は、子供が宣言された順序に頼らない限り、悪い考えです。あなたがその注文に頼っていない場合は、適切なxとyの値を持つものを見つけるために子供のリストを辿る必要があります。つまり、各子供の子供のリストを歩かなければなりません。その’はO(n²)操作です(読んでください:かなり非効率的です)。数学もかなり複雑です。ここで

1

  • (一番上にあることの最後で)どの順番で描かれます子供のどの調整する方法としてgetChildDrawingOrder

    1. を上書きする方法を示して簡単な例である秩序を持っていますイベントをクリック/タップから変更

    RelativeLayoutクラス:

    public class AlternatingChildDrawingOrderRelativeLayout extends RelativeLayout { 
    
        // the childDrawingOrder modifier 
        private int childDrawingOrderModifier = 0; 
    
        public AlternatingChildDrawingOrderRelativeLayout(Context context) { 
         super(context); 
         init(context); 
        } 
    
        void init(Context context) { 
         setClickable(true); 
         setChildrenDrawingOrderEnabled(true); 
         setOnClickListener(new OnClickListener() { 
          @Override 
          public void onClick(View v) { 
           // increment to adjust the child drawing order 
           childDrawingOrderModifier++; 
           // call invalidate to redraw with new order modifier 
           ViewCompat.postInvalidateOnAnimation(v); 
          } 
         }); 
        } 
    
        @Override 
        protected int getChildDrawingOrder(int childCount, int i) { 
         // increment i with the modifier, then afford for out of bounds using modulus of the child count 
         int returnValue = (i + childDrawingOrderModifier) % childCount; 
         Log.v(VIEW_LOG_TAG, "getChildDrawingOrder returnValue=" + returnValue + " i=" + i); 
         return returnValue; 
        } 
    
        public AlternatingChildDrawingOrderRelativeLayout(Context context, AttributeSet attrs) { 
         super(context, attrs); 
         init(context); 
        } 
    
        public AlternatingChildDrawingOrderRelativeLayout(Context context, 
                     AttributeSet attrs, 
                     int defStyleAttr) { 
         super(context, attrs, defStyleAttr); 
         init(context); 
        } 
    
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
        public AlternatingChildDrawingOrderRelativeLayout(Context context, 
                     AttributeSet attrs, 
                     int defStyleAttr, 
                     int defStyleRes) { 
         super(context, attrs, defStyleAttr, defStyleRes); 
         init(context); 
        } 
    
    } 
    
    それは左側に

    Starting Draw order (blue) First tap (red) Second tap (green

    。写真のように見える何

    のxmlレイアウト

    <?xml version="1.0" encoding="utf-8"?> 
    <com.example.ui.AlternatingChildDrawingOrderRelativeLayout 
        xmlns:android="http://schemas.android.com/apk/res/android" 
        android:layout_width="300dp" 
        android:layout_height="300dp"> 
    
        <View 
         android:id="@+id/red" 
         android:layout_width="125dp" 
         android:layout_height="300dp" 
         android:layout_alignParentLeft="true" 
         android:layout_alignParentStart="true" 
         android:background="#f00" 
         /> 
    
        <View 
         android:id="@+id/green" 
         android:layout_width="125dp" 
         android:layout_height="300dp" 
         android:layout_centerInParent="true" 
         android:background="#0f0"/> 
    
        <View 
         android:id="@+id/blue" 
         android:layout_width="125dp" 
         android:layout_height="300dp" 
         android:layout_alignParentRight="true" 
         android:layout_alignParentEnd="true" 
         android:background="#00f"/> 
    
    </com.example.ui.AlternatingChildDrawingOrderRelativeLayout> 
    

    デフォルトはに基づいている描画開始ため、ありますxmlレイアウト:

    最初から最後まで(または、下から上に向かって)考えると、赤、緑、青です。ここgetChildDrawingOrderのログ・ダンプが途中で

    V/View: getChildDrawingOrder returnValue=0 i=0 
    V/View: getChildDrawingOrder returnValue=1 i=1 
    V/View: getChildDrawingOrder returnValue=2 i=2 
    

    に呼び出されて、私たちの最初のタップした後、右側に、

    V/View: getChildDrawingOrder returnValue=1 i=0 
    V/View: getChildDrawingOrder returnValue=2 i=1 
    V/View: getChildDrawingOrder returnValue=0 i=2 
    

    赤と緑、青の順序の変更は、私たちを示してどのような注文がBlue、Red、Greenに変更されてから2番目のタップの後に表示されます。

    V/View: getChildDrawingOrder returnValue=2 i=0 
    V/View: getChildDrawingOrder returnValue=0 i=1 
    V/View: getChildDrawingOrder returnValue=1 i=2 
    

    それが戻っ青が最後だった元の順序に

    HTHS係数計算のために描画するこのかなりのループの後に任意のタップ!

  • +0

    これはもう少し紹介が必要なような気がします。私は何年もAndroidの開発から離れていましたので、このコードを読み、それが何をしているのかを理解するために少し掘り下げなければなりません。それをしなければ、私はこれが良い答えであるかどうかは分からない。 'getChildDrawingOrder'とそれがどのように動作するか/それがどのように使用されているかについてのより多くの説明はそれを助けるでしょう、と私は思います。 – KRyan

    +0

    説明のためにいくつかの画像を追加します – petey

    関連する問題