2013-01-24 30 views
5

Tôi đang tạo bản đồ đẳng bằng các ô đơn giản và tôi ’ đã mở rộng RelativeLayout để tạo bố cục chứa các ô này. Thực sự, chỉ cần sử dụng một số RelativeLayout as-được làm việc tốt miễn là định hướng của tôi khớp với thứ tự mà các lát được ghi vào tệp XML; tất cả tôi ’ đã ghi đè là các nhà xây dựng, nơi tôi chỉ cần gọi supersetChildrenDrawingOrderEnabled(true); cùng với việc thiết lập một số biến (chiều cao và chiều rộng của lưới), và sau đó getChildDrawingOrder chính nó.getChildDrawingOrder được gọi/sử dụng không đúng?

Mã của tôi cho getChildDrawingOrder số liệu ra các chỉ số mới cho đứa trẻ nào đó, và cũng có thể đặt ra một chuỗi trong con để i->i', nơi i là chỉ số gốc và i' là chỉ số mới. Tôi ’ m bằng cách này để thử nghiệm; trẻ em được thiết lập để vẽ chuỗi này trên bản thân cùng với tọa độ của chúng.

Thật không may, nó không hoạt động chính xác, hoặc đúng hơn là nó hoạt động không chính xác. Trong số 9 ô trong trường hợp thử nghiệm của tôi, có ba số là ’ t dường như có getChildDrawingOrder gọi là: chuỗi tôi đã đề cập ở trên là null. Trong số còn lại, ít nhất một được rút ra khỏi trật tự mặc dù nhận được chỉ số chính xác thông qua nó.

Đây ’ sa hình ảnh (trong định hướng TOP):

Image of getChildDrawingOrder failure

Chú ý rằng (0,2), (1,2), và (2,1) đều được liệt kê như NULL, và do đó, getChildDrawingOrder dường như chưa bao giờ được gọi cho họ. Cũng lưu ý rằng (1,0) được vẽ trên đầu (1,1), mặc dù cả hai số i (3) và i' (1) nhỏ hơn (1,1) ’ s (4 và 4 tương ứng).

Đây ’ là mã từ 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; 
    } 
} 

bất cứ ai có thể làm sáng tỏ về những gì ’ đang xảy ra? Tại sao isn ’ t getChildDrawingOrder được gọi cho ba loại gạch đó? Tại sao (1.0) được vẽ theo thứ tự sai, mặc dù getChildDrawingOrder được gọi?

Trả lời

10

OK, đã tìm ra bằng cách xem mã nguồn Android. Tôi đã lập bản đồ của getChildDrawingOrder: số i được thông qua là “ con tôi nên vẽ i thứ? ” không phải "khi nào tôi nên vẽ con tôi?" Lý do cho các NULL s là vì những trẻ em đã được rút ra trước khi i của riêng mình đã được thông qua.

Tôi đã thay đổi mã của mình để tìm ra thứ tự cho tất cả trẻ em trong thẻ onMeasure, lưu điều đó vào SparseIntArray và sau đó chỉ trả lại từ getChildDrawingOrder. Những công việc này.

Tính lại chỉ mục theo hàm getChildDrawingOrder, bằng cách này, là ý tưởng tồi trừ khi bạn muốn dựa vào thứ tự mà trẻ em được khai báo. Bởi vì nếu bạn don ’ t dựa vào thứ tự đó, bạn phải đi qua danh sách trẻ em để tìm một trong đó có giá trị x và y thích hợp, có nghĩa là bạn phải đi qua danh sách trẻ em cho mỗi đứa trẻ. Điều đó ’ s một hoạt động O (n²) (đọc: khá kém hiệu quả). Toán học cũng phức tạp một cách hợp lý.

1

Đây là một ví dụ đơn giản cho thấy làm thế nào để ghi đè getChildDrawingOrder

  1. như một cách để điều chỉnh nào trong số trẻ em được rút ra trong đó trật tự (với người cuối cùng trên là trên đầu trang)
  2. có thứ tự thay đổi từ một vòi nước/nhấp kiện

lớp 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); 
    } 

} 

Cách bố trí 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> 

gì nó trông giống như

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

Trong hình bên trái là để bắt đầu vẽ, đó là mặc định dựa trên bố cục xml:

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

Vì vậy, từ đầu đến cuối (hoặc nghĩ từ dưới lên trên) là: Đỏ, Xanh lục, Xanh lam. Dưới đây là những bãi nhật ký của getChildDrawingOrder được gọi

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

Ở giữa, sau khi tap đầu tiên của chúng tôi, những thay đổi để màu xanh lá cây, xanh da trời, đỏ

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

Và, ở phía bên phải cho chúng ta thấy những gì nó trông giống như sau lần nhấn thứ hai của chúng tôi kể từ khi lệnh thay đổi thành: Xanh lam, Đỏ, Xanh lục.

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

Bất kỳ tap sau này khá nhiều vòng nó trở lại trật tự ban đầu nơi xanh lần cuối được rút ra do việc tính toán mô đun

HTHs!

+0

Tôi cảm thấy như thế này cần thêm một chút giới thiệu. Tôi đã đi từ phát triển Android trong nhiều năm, vì vậy tôi sẽ phải đào một chút để có được vào mã này và hiểu những gì nó đã làm. Nếu không làm điều đó, tôi thậm chí không thể nói đây có phải là câu trả lời hay không. Giải thích thêm về 'getChildDrawingOrder' và cách nó hoạt động/cách nó được sử dụng sẽ giúp ích gì với điều đó, tôi nghĩ vậy. – KRyan

+0

Tôi sẽ thêm một số hình ảnh để minh họa – petey

Các vấn đề liên quan