2010-08-06 31 views
26

Về cơ bản, đây là cấu trúc phân cấp của tôi (và tôi thích ứng dụng nếu khó đọc ... Tôi mới ở đây để gửi đề xuất một cách vui vẻ chấp nhận)Vô hiệu hóa chạm trên nền UIView sao cho các nút ở chế độ xem thấp hơn có thể bấm


--AppControls.xib
------- (UIView) ControlsView
----------------- (UIView) TopBar
--- -------------- -------------- btn1, btn2, btn3
--------------- - UIView) BottomBar
----------------- - ------------- slider1 btn1, btn2
--PageContent.xib
----------------- (UIView) ContentView
- ---------------- -------------- btn1, btn2, btn3
------------- ---- -------------- (UIImageView) FullPageImage


tình hình của tôi là tôi muốn ẩn và hiển thị các điều khiển khi khai thác bất cứ nơi nào trên PageContent không thats một và có các nút điều khiển hiển thị, giống như Trình phát video trên iPhone. Tuy nhiên, khi các điều khiển được hiển thị, tôi vẫn muốn có thể nhấp vào các nút trên PageContent.

Tôi có tất cả công việc này, ngoại trừ bit cuối cùng. Khi các điều khiển hiển thị nền của các nút điều khiển nhận được các sự kiện cảm ứng thay vì chế độ xem bên dưới. Và tắt tương tác người dùng trên ControlsView sẽ tắt nó trên tất cả các con của nó.

Tôi đã cố gắng trọng hitTest trên lớp con ControlsView của tôi như sau đó tôi tìm thấy trong một bài tương tự:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ 
UIView *hitView = nil; 
NSArray *subviews = [self subviews]; 
int subviewCount = [subviews count]; 
for (int subviewIndex = 0; !hitView && subviewIndex < subviewCount; subviewIndex++){ 
hitView = [[subviews objectAtIndex:subviewIndex] hitTest:point withEvent:event]; 
} 
return hitView; 
} 

Tuy nhiên, vào thời điểm này thanh trượt của tôi không hoạt động, cũng không phải làm hầu hết các nút khác, và thực sự, mọi thứ bắt đầu trở nên kỳ lạ.

Câu hỏi của tôi ngắn gọn: Làm cách nào để cho phép tất cả các lượt xem của chế độ xem có sự kiện chạm, trong khi nền của chế độ xem siêu không thể nhấp được và các nút trên chế độ xem bên dưới có thể nhận sự kiện chạm.

Cảm ơn!

Trả lời

60

Bạn thân thiết. Đừng ghi đè -hitTest:withEvent:. Vào thời điểm được gọi, người điều phối sự kiện đã quyết định rằng cây con của bạn trong phân cấp sở hữu sự kiện và sẽ không tìm ở nơi khác. Thay vào đó, hãy ghi đè -pointInside:withEvent:, được gọi trước đó trong đường ống xử lý sự kiện. Đó là cách hệ thống hỏi "xem hey, có ai trong hệ thống phân cấp của bạn phản ứng với một sự kiện vào thời điểm này không?". Nếu bạn nói KHÔNG, xử lý sự kiện tiếp tục bên dưới bạn trong ngăn xếp hiển thị.

Mỗi documentation, việc triển khai mặc định chỉ kiểm tra xem liệu điểm đó có nằm trong giới hạn của chế độ xem hay không.

Chiến lược của bạn là để nói "có" khi bất kỳ bản xem trước nào của bạn ở tọa độ đó, nhưng nói "không" khi chạm sẽ chạm vào nền.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    for (UIView * view in [self subviews]) { 
     if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) { 
      return YES; 
     } 
    } 
    return NO; 
} 
+1

Perfect! Cảm ơn bạn rất nhiều! – averydev

+1

Bạn được chào đón. Tôi đã chiến đấu với cùng một vấn đề này trong nhiều giờ một lần. Vui vẻ giúp đỡ. –

+0

Nhân tiện, đó có phải là ít hơn một cách propper để vẽ đồ thị phân cấp không? Hoặc là có một thực hành tiêu chuẩn? – averydev

1

Cách tiếp cận khác có thể là có nút toàn màn hình ẩn đằng sau mọi thứ khác và thực hiện hành động thích hợp khi nó được nhấn.

+0

Điều đó nghe như một ý tưởng khủng khiếp. –

1

Một biến thể nhỏ về câu trả lời của Ben, xử lý w/trẻ em mở rộng bên ngoài cha mẹ. Nếu clipTrẻ em là CÓ, thì điều này sẽ không trả lại CÓ cho các điểm nằm ngoài tầm kiểm soát chính nhưng bên trong một số trẻ em. nếu clipTrẻ em là KHÔNG, điều này giống với của Ben.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    BOOL clipChildren = YES; 

    if (!clipChildren || [super pointInside:point withEvent:event]) { 
     for (UIView * view in [self subviews]) { 
      if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) { 
       return YES; 
      } 
     } 
    } 
    return NO; 
} 
2

Nhờ @Ben Zutto, Swift 3 giải pháp:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 
    for view in self.subviews { 
     if view.isUserInteractionEnabled, view.point(inside: self.convert(point, to: view), with: event) { 
      return true 
     } 
    } 

    return false 
} 
Các vấn đề liên quan