2013-03-14 42 views
25

Đối với hằng số UIKeyboardFrameEndUserInfoKey, trong các tài liệu của Apple nó nói:Chuyển đổi UIKeyboardFrameEndUserInfoKey để xem hoặc Window Tọa

Những tọa độ không đưa vào tài khoản bất kỳ luân chuyển các yếu tố áp dụng cho nội dung của cửa sổ như là kết quả của định hướng giao diện thay đổi. Do đó, bạn có thể cần phải chuyển đổi hình chữ nhật sang cửa sổ tọa độ (sử dụng phương thức convertRect: fromWindow:) hoặc để xem các tọa độ (sử dụng phương thức convertRect: fromView:) trước khi sử dụng nó.

Vì vậy, nếu tôi sử dụng [view1 convertRect:rect fromView:view2]

tôi sẽ chèn gì cho các thông số trên để có được nó để chuyển đổi các giá trị luân chuyển một cách chính xác? tức là:

view1 =? rect =? (khung bàn phím tôi giả định) view2 =?

Đã thử một số thứ và nhận một số nội dung thú vị.

+0

Hy vọng câu trả lời dưới đây sẽ giúp. Trước đây tôi cũng đã sử dụng 'conversionRect', nhưng mã bên dưới là sạch hơn, IMO. – memmons

+0

Rõ ràng là tôi không đồng ý với @Answerbot về những gì "sạch hơn" :) BTW mã tôi hiển thị đến từ cuốn sách của tôi, mà bạn có thể muốn tham khảo về vấn đề này: http://www.apeth.com/iOSBook/ ch23.html # _summoning_and_dismissing_the_keyboard – matt

+0

@matt Nội dung hay. Tôi đã đọc một trong những cuốn sách của bạn và thực sự thích nó. Lý do tôi ngừng sử dụng bằng cách sử dụng 'conversionRect' là bởi vì nó chỉ thực sự hoạt động tốt bên trong một bộ điều khiển xem nơi bạn có' myView' đại diện cho khung nhìn trên cùng. Tuy nhiên, nếu bạn đang nghe các thông báo từ bên trong một lớp con 'UITextField', việc chuyển đổi bằng cách sử dụng self không đặc biệt hữu ích. – memmons

Trả lời

66

Chế độ xem đầu tiên phải là chế độ xem của bạn. Khung nhìn thứ hai phải là nil, có nghĩa là tọa độ cửa sổ/màn hình. Do đó:

NSDictionary* d = [notification userInfo]; 
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
r = [myView convertRect:r fromView:nil]; 

Bây giờ bạn có phần chỉnh sửa mà bàn phím sẽ chiếm, theo quan điểm của bạn. Nếu chế độ xem của bạn là chế độ xem của trình điều khiển chế độ xem hiện tại (hoặc chế độ xem phụ của chế độ xem đó), thì xoay vòng và v.v ... hiện được tính.

+4

+1, nhưng tôi nghĩ điều này chỉ hữu ích nếu 'myView' đại diện cho chế độ xem gốc của trình điều khiển chế độ xem. Điều gì nếu nó không mặc dù và thay vào đó myView là một subview như '{100,100,200,200}'? – memmons

+1

Hãy nhận biết rằng bạn cũng cần phải chuyển đổi hệ thống tọa độ trực tràng sang cửa sổ! Câu trả lời từ @ david-m-syzdek hoàn chỉnh hơn. –

+1

@DiogoTridapalli Chỉ cần rõ ràng, trong iOS 8 không cần phải chuyển đổi qua hệ tọa độ cửa sổ để xử lý trường hợp định hướng ngang, bởi vì toàn bộ ứng dụng quay và bàn phím đã xoay với nó. – matt

21

Tôi đã thử câu trả lời được chấp nhận và thấy rằng nó không thực sự cung cấp CGRect của bàn phím trong chế độ xem. Tôi thấy rằng tôi phải chuyển đổi CGRect từ đối tượng UIScreen đến đối tượng UIWindow, và từ đối tượng UIWindow đến đối tượng UIView:

NSValue * keyboardEndFrame; 
CGRect screenRect; 
CGRect windowRect; 
CGRect viewRect; 

// determine's keyboard height 
screenRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
windowRect = [self.view.window convertRect:screenRect fromWindow:nil]; 
viewRect  = [self.view  convertRect:windowRect fromView:nil]; 

tôi sử dụng ở trên để thay đổi kích thước xem gốc để không bị ẩn bởi bàn phím:

NSTimeInterval duration; 
CGRect   frame; 

// determine length of animation 
duration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 

// resize the view 
frame    = self.view.frame; 
frame.size.height -= viewRect.size.height; 

// animate view resize with the keyboard movement 
[UIView beginAnimations:nil context:NULL]; 
[UIView setAnimationBeginsFromCurrentState:YES]; 
[UIView setAnimationDuration:duration]; 
self.view.frame = frame; 
[UIView commitAnimations]; 
+0

Tôi gặp phải trường hợp tôi phải làm điều này. Vì vậy, tôi sẽ làm theo cách này từ bây giờ. – ma11hew28

+0

Tôi đang sử dụng phương pháp này, nhưng nhận được giá trị 'origin' không chính xác của viewRect cho định hướng ngang (âm' y'). Trong giải pháp của bạn, bạn chỉ sử dụng 'chiều cao'. Liệu 'origin' của bạn có chứa giá trị' y' đúng không? – burax

1
+ (void)parseKeyboardNotification:(NSNotification *)notification 
       inRelationToView:(UIView *)view 
          info:(void(^)(NSTimeInterval keyboardAnimationDuration, CGRect keyboardFrameInView, UIViewAnimationOptions keyboardAnimationOptions))callback 
{ 
    NSParameterAssert(notification != nil); 
    NSParameterAssert(view != nil); 

    NSDictionary *userInfo = [notification userInfo]; 

    UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 
    UIViewAnimationOptions animationOption = animationCurve << 16; // https://devforums.apple.com/message/878410#878410 
    NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 

    // http://stackoverflow.com/a/16615391/202451 
    CGRect screenRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
    CGRect windowRect = [view.window convertRect:screenRect fromWindow:nil]; 
    CGRect viewRect  = [view  convertRect:windowRect fromView:nil]; 

    callback(animationDuration, viewRect, animationOption); 
} 

có thể được sử dụng như thế này

- (void)keyboardWillShowOrHide:(NSNotification *)notification 
{  
    [AGKeyboardInfo parseKeyboardNotification:notification inRelationToView:self.view info:^(NSTimeInterval keyboardAnimationDuration, CGRect keyboardFrameInView, UIViewAnimationOptions keyboardAnimationOptions) { 

     [UIView animateWithDuration:keyboardAnimationDuration delay:0 options:keyboardAnimationOptions animations:^{ 

      // do any modifications to your views 

     } completion:nil]; 
    }]; 
} 
Các vấn đề liên quan