2009-02-20 14 views
6

Tôi có UIPickerView bị mờ dần tới 20% alpha khi không sử dụng. Tôi muốn người dùng có thể chạm vào bộ chọn và làm mờ dần.Trả lời lần chạmBán trong UIPickerXem thay vì UIView

Tôi có thể làm việc đó nếu tôi đặt phương thức touchesBegan trên Chế độ xem chính nhưng điều này chỉ hoạt động khi người dùng chạm vào Chế độ xem. Tôi đã thử sub-classing UIPickerView và có một touchesBegan trong đó, nhưng nó không hoạt động.

Tôi đoán nó liên quan đến chuỗi Responder, nhưng dường như không thể giải quyết được.

Trả lời

10

Tôi đã tìm kiếm giải pháp cho vấn đề này trong hơn một tuần. Tôi trả lời bạn ngay cả khi bạn đang đặt câu hỏi là hơn một tuổi, hy vọng điều này sẽ giúp người khác.

Xin lỗi nếu ngôn ngữ của tôi không phải là rất kỹ thuật, nhưng tôi khá mới để phát triển Objective-C và iPhone.

Tạo lớp con UIpickerView là cách đúng để thực hiện. Nhưng bạn đã ghi đè phương thức - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event. Đây là phương pháp được gọi bất cứ khi nào bạn chạm vào màn hình và nó sẽ trả lại chế độ xem sẽ phản ứng với lần chạm. Nói cách khác, chế độ xem có phương thức touchesBegan:withEvent: sẽ được gọi.

UIPickerView có 9 lượt xem phụ! Trong việc thực thi lớp UIPickerView, - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event sẽ không trả về self (điều này có nghĩa là bạn sẽ không được gọi) touchesBegan:withEvent:, nhưng sẽ trả về một khung nhìn con, chính xác khung nhìn ở chỉ mục 4 (một lớp con không được đặt tên là UIPickerTable).

Bí quyết là để làm cho phương pháp - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event trở self vì vậy bạn có thể kiểm soát các touchesBegan:withEvent:, touchesMoved:withEvent:touchesEnded:withEvent: phương pháp.

Trong các phương pháp này, để giữ các chức năng tiêu chuẩn của UIPickerView, bạn PHẢI nhớ gọi lại chúng nhưng trên UIPickerTable subview.

Tôi hy vọng điều này có ý nghĩa. Tôi không thể viết mã ngay bây giờ, ngay khi tôi ở nhà, tôi sẽ chỉnh sửa câu trả lời này và thêm một số mã.

8

Dưới đây là một số mã mà những gì bạn muốn:

@interface TouchDetectionView : UIPickerView { 

} 
- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event; 
@end 
@implementation TouchDetectionView 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesBegan:touches withEvent:event]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesMoved:touches withEvent:event]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesEnded:touches withEvent:event]; 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesCancelled:touches withEvent:event]; 
} 

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    return self; 
} 

- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UITouch * touch = [touches anyObject]; 
    CGPoint point = [touch locationInView:self]; 
    UIView * hitTestView = [super hitTest:point withEvent:event]; 

    return (hitTestView == self) ? nil : hitTestView; 
} 
+0

nhờ nó làm việc :) – ArunGJ

+1

mã này dường như làm việc, trừ khi một liên lạc xảy ra trên khung đó ngay lập tức bao quanh bánh xe chọn. làm điều đó dường như gây ra một vòng lặp vô hạn các cuộc gọi đến phương thức getNextResponderView: withEvent:. – pistachionut

+1

ya i ngăn chặn nó bằng cách trả về nil thay vì hitTestView từ getNextResponderView: withEvent: nếu tôi chạm vào bánh xe xung quanh. – ArunGJ

1

Cả hai câu trả lời trên là rất hữu ích, nhưng tôi có một UIPickerView lồng trong một UIScrollView. Tôi cũng đang liên tục hiển thị ở nơi khác trên màn hình trong khi GUI có mặt. Vấn đề là UIPickerView không cập nhật đầy đủ khi: một hàng không được chọn được khai thác, bộ chọn được di chuyển sao cho hai hàng nằm giữa vùng lựa chọn hoặc một hàng được kéo nhưng các ngón tay trượt ra ngoài UIPickerView. Sau đó, nó không phải cho đến khi UIScrollView được di chuyển mà bộ chọn ngay lập tức cập nhật. Kết quả này là xấu.

Nguyên nhân của sự cố: hiển thị liên tục của tôi đã giữ hoạt ảnh của UIPickerView không nhận được chu kỳ CPU cần thiết để hoàn thành, do đó hiển thị lựa chọn chính xác, hiện tại. Giải pháp của tôi - công trình nào-- là điều này: trong touchesEnded:withEvent: của UIPickerView, hãy thực hiện một cái gì đó để tạm dừng hiển thị của tôi trong một thời gian ngắn. Dưới đây là các mã:

#import "SubUIPickerView.h" 

@implementation SubUIPickerView 

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    [pickerTable touchesBegan:touches withEvent:event]; 
} 

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    [pickerTable touchesMoved:touches withEvent:event]; 
} 

- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    [singleton set_secondsPauseRendering:0.5f]; // <-- my code to pause rendering 

    [pickerTable touchesEnded:touches withEvent:event]; 
} 

- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    [pickerTable touchesCancelled:touches withEvent:event]; 
} 

- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    if (CGRectContainsPoint(self.bounds, point)) 
    { 
     if (pickerTable == nil) 
     { 
      int nSubviews = self.subviews.count; 
      for (int i = 0; i < nSubviews; ++i) 
      { 
       UIView* view = (UIView*) [self.subviews objectAtIndex:i]; 
       if ([view isKindOfClass:NSClassFromString(@"UIPickerTable")]) 
       { 
        pickerTable = (UIPickerTable*) view; 
        break; 
       } 
      } 
     } 
     return self; // i.e., *WE* will respond to the hit and pass it to UIPickerTable, above. 
    } 
    return [super hitTest:point withEvent:event]; 
} 

@end 

và sau đó là tiêu đề, SubUIPickerView.h:

@class UIPickerTable; 

@interface SubUIPickerView : UIPickerView 
{ 
    UIPickerTable* pickerTable; 
} 

@end 

Như tôi đã nói, công trình này.Hiển thị tạm dừng thêm 1/2 giây (nó đã tạm dừng khi bạn trượt UIScrollView) cho phép hoạt ảnh UIPickerView kết thúc. Sử dụng NSClassFromString() có nghĩa là bạn không sử dụng bất kỳ API không có giấy tờ nào. Lộn xộn với chuỗi Responder là không cần thiết. Nhờ checcco và Tylerc230 đã giúp tôi tìm ra giải pháp của riêng mình!

+0

Tính năng này không hoạt động với UIPickerView của iOS 8 nữa. – MatthiasC

+0

@MatthiasC bạn có biết tại sao nó không hoạt động nữa không? – stonedauwg

+0

Những bài đăng về UIPickerView này thực sự cũ. Đó là mới & flakey trở lại sau đó. Apple đã có thể (hy vọng) hoàn toàn reimplemented nó ngay bây giờ! – electromaggot

0

Set canCancelContentTouches và delaysContentTouches nhìn mẹ để NO, mà làm việc cho tôi