2012-04-04 55 views
7

Tôi đang triển khai một trò chơi solitaire iOS đơn giản cho phép người dùng kéo thẻ xung quanh theo cách thông thường. Các thẻ được trình bày với các lớp con UIViewCardView. Tất cả các dạng xem của thẻ là anh chị em, là các phần phụ của SolitaireView. Đoạn mã sau cố gắng "mang thẻ vào mặt trước" để nó ở trên tất cả các chế độ xem khác khi đang được kéo:UIView bringSubviewToFront: không * không * hiển thị chế độ xem trước

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    if (touch.view.tag == CARD_TAG) { 
     CardView *cardView = (CardView*) touch.view; 
     ... 
     [self bringSubviewToFront:cardView]; 
     ... 
    } 
} 

Thật không may, thứ tự z của thẻ vẫn không thay đổi trong khi kéo. Trong những hình ảnh dưới đây, tôi đang kéo vua. Chú ý nó như thế nào là đúng trên đỉnh Cửu trong hình ảnh bên trái, nhưng là sai dưới Hai (dưới toàn bộ đống trên thực tế) trong hình ảnh bên phải:

enter image description hereenter image description here

Tôi cũng đã cố gắng thay đổi thuộc tính như layer.zPosition cũng không có kết quả. Làm thế nào tôi có thể mang lại giao diện thẻ ở mặt trước trong khi kéo? Tôi bị hoang mang.

+0

tôi phát hiện ra rằng 'bringSubviewToFront:' gây 'needsLayout' cờ của view được thiết lập. Phương thức 'layoutSubviews' của tôi cũng đang gọi' bringSubviewToFront: 'do đó hoàn nguyên tất cả các lệnh xem z trở về trạng thái ban đầu của chúng! – wcochran

+0

Vậy thì giải pháp cho việc này là gì? Tôi cũng có cùng một loại yêu cầu, từ danh sách thẻ, nếu tôi chọn bất kỳ thẻ đặt hàng ở giữa nào, nó sẽ xuất hiện, sau đó đi lên phía trước. nhưng hoạt ảnh của tôi không hoạt động vì mangSubviewToFront: phương thức – Mrunal

+0

Nếu bạn gắn bó với việc sử dụng các lớp con UIView thì bạn cần đánh dấu thẻ đang được kéo để layoutSubviews có thể đặt nó lên trên cùng. Tôi thực sự chuyển sang sử dụng CALayers như đã đề cập dưới đây. – wcochran

Trả lời

8

Đã xác nhận. bringSubviewToFront: làm cho số layoutSubview được gọi. Vì phiên bản layoutSubviews của tôi đặt đơn đặt hàng z trên tất cả các chế độ xem, điều này đã hoàn tác đơn đặt hàng z tôi đã đặt trong mã touchesBegan:withEvent ở trên. Apple nên đề cập đến tác dụng phụ này trong tài liệu bringSubviewToFront.

Thay vì sử dụng lớp con UIView, tôi đã tạo một lớp con CALayer có tên là CardLayer. Tôi xử lý các liên lạc trong lớp con KlondikeView của tôi như được liệt kê dưới đây. topZPosition là một var thể hiện theo dõi zPosition cao nhất của tất cả các thẻ. Lưu ý rằng sửa đổi zPosition thường hoạt hình - Tôi tắt chức năng này trong các mã dưới đây:

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { 
    UITouch *touch = [touches anyObject]; 
    CGPoint touchPoint = [touch locationInView:self]; 
    CGPoint hitTestPoint = [self.layer convertPoint:touchPoint 
              toLayer:self.layer.superlayer]; 
    CALayer *layer = [self.layer hitTest:hitTestPoint]; 

    if (layer == nil) return; 

    if ([layer.name isEqual:@"card"]) { 
    CardLayer *cardLayer = (CardLayer*) layer; 
    Card *card = cardLayer.card; 

    if ([self.solitaire isCardFaceUp:card]) { 
     //...                            
     [CATransaction begin]; // disable animation of z change                 
     [CATransaction setValue:(id)kCFBooleanTrue 
         forKey:kCATransactionDisableActions];    
     cardLayer.zPosition = topZPosition++; // bring to highest z 

     // ... if card fan, bring whole fan to top 

     [CATransaction commit]; 
     //...                            
    } 
    // ...                            
    } 

} 
+4

Tôi nghĩ rằng việc sử dụng thẻ của UIView' có thể là một lựa chọn thiết kế tồi - tôi không nghĩ chúng thực sự được dự định cho điều này. Tôi nghĩ tôi sẽ lùi lại và sử dụng 'CALayer'. – wcochran

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