2013-01-24 56 views
5

我正在用簡單的瓷磚創建等軸測圖,並且我擴展了RelativeLayout以創建一個包含這些瓷磚的佈局。真的,只要使用RelativeLayout as-is工作正常,只要我的方向與磁貼寫入XML文件的順序相匹配;所有我’ ve被覆蓋的構造函數,我簡單地調用supersetChildrenDrawingOrderEnabled(true);以及設置一些變量(網格的高度和寬度),然後getChildDrawingOrder本身。getChildDrawingOrder調用/使用不規律?

我對getChildDrawingOrder數字出新的指數給定的子碼,並且還設置在孩子i->i',其中i是原來的指數,i'是新指數的字符串。 I ’ m用於測試;孩子們可以將自己的字符串和他們的座標一起畫出來。

不幸的是,它不能正常工作,或者說它工作不正常。在我測試用例中的九塊瓷磚中,三塊瓷磚似乎都有getChildDrawingOrder:上面提到的字符串是null。其餘的是,儘管得到正確的索引,但其中至少有一個正在被排除在外。

這裏’ SA圖片(在TOP取向):

Image of getChildDrawingOrder failure

注意,(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; 
    } 
} 

任何人都可以擺脫什麼’事了一些輕?爲什麼要爲這三個瓷磚調用?’ t getChildDrawingOrder?爲什麼(1,0)以錯誤的順序繪製,即使getChildDrawingOrder被調用?

回答

10

好的,通過查看Android源代碼來計算出來。我有getChildDrawingOrder的映射:通過i是「哪個孩子應該畫 th? 」不是「我應該什麼時候畫小孩嗎?」 NULL的原因是因爲這些孩子在他們自己的i通過之前被抽中。

我改變了我的代碼onMeasure傳中找出所有兒童的順序,保存在一個SparseIntArray,然後剛剛返回,從getChildDrawingOrder。這工作。

順便說一句,反向計算getChildDrawingOrder函數中的索引是一個壞主意,除非您想依賴聲明子級的順序。因爲如果你不依賴那個順序,你必須遍歷兒童列表來找到具有合適的x和y值的列表,這意味着你必須遍歷每個孩子的兒童列表。 ’是一個O(n²)操作(讀取:相當低效)。數學也相當複雜。

1

下面是一個簡單的例子,演示如何重寫getChildDrawingOrder

  1. ,以此來調整它的孩子以何種順序被抽取(與最後的是在上面)
  2. 有秩序從水龍頭更改/單擊事件

的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); 
    } 

} 

的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> 

它看起來像什麼

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

圖爲左邊是基於開始繪製順序,這是默認xml佈局:

Red = index 0 
Green = index 1 
Blue = index 2 

因此,從頭到尾(或從低到高)即:紅色,綠色,藍色。這裏是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 

而且,在右側顯示了我們什麼它看起來像在我們第二次點擊後,因爲訂單更改爲:藍色,紅色,綠色。

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