2013-05-23 7 views
5

Próbuję przenieść UIScrollView, gdy klawiatura ukrywa UITextField, zmieniając rozmiar za pomocą contentInsets, jak pokazano.Składniki zawartości UIScrollView nie działają dla Wysokość klawiatury

Nie działa jednak dla wysokości klawiatury. Wysokość klawiatury wynosi 216, ale zatrzymuje się tylko przewijanie w prawidłowej lokalizacji, jeśli ustawię dolną wstawkę na 515 dla trybu pionowego iPhone'a i 310 dla trybu poziomego iPhone'a. Dlaczego te wymiary byłyby tak różne? Nie chcę hardcode tych arbitralnych wartości

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.view.frame = self.parentViewController.view.frame; 

    [self.textView becomeFirstResponder]; 

    NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width); 

    [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWasShown:) 
              name:UIKeyboardDidShowNotification 
              object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWillHide:) 
              name:UIKeyboardWillHideNotification 
              object:nil]; 
} 

- (void)keyboardWasShown:(NSNotification *)notification 
{ 
    if([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone) { 

     // Step 1: Get the size of the keyboard. 
     CGFloat keyboardHeight = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; 

     // Step 2: Adjust the bottom content inset of your scroll view by the keyboard height. 
     UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0); 
     ((UIScrollView*)self.view).contentInset = contentInsets; 
     ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; 

     // Step 3: Scroll the target text field into view. 
     CGRect aRect = self.view.frame; 
     aRect.size.height = aRect.size.height - keyboardHeight; 
     if (!CGRectContainsPoint(aRect, self.textView.frame.origin)) { 
      CGPoint scrollPoint = CGPointMake(0.0, self.textView.frame.origin.y - keyboardHeight); 
      [((UIScrollView*)self.view) setContentOffset:scrollPoint animated:YES]; 
     } 
    } 
} 

- (void) keyboardWillHide:(NSNotification *)notification { 
    UIEdgeInsets contentInsets = UIEdgeInsetsZero; 
    ((UIScrollView*)self.view).contentInset = contentInsets; 
    ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; 
} 

Edit.

Przed klawiatura jest otwarty, i drukować na to uwagę:

NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width); 

i drukuje to:

scrollview: 431.000000,320.000000, parent: 431.000000,320.000000 
+0

jest przewijanie dobrze bez klawiatury, możliwe, że podałeś wysokość większą niż wysokość widoku nadrzędnego. –

+0

Tak. To jest przewijanie dobrze – Kristin

+0

Chcę poznać ramkę przewijania i jego rodzica ramki widoku przed otwarciem klawiatury. –

Odpowiedz

21

Myślę, że głównym problemem jest to, że musisz użyć UIKeyboardFrameEndUserInfoKey zamiast UIKeyboardFrameBeginUserInfoKey.

Mając na uwadze powyższe, napisałem inną wersję tej metody, która będzie działać, nawet jeśli Scrollview nie jest umieszczona w dolnej części ekranu i może działać lepiej dla Ciebie:

Zauważ, że używam self.activeTextField zamiast z self.textField.

// Called when the UIKeyboardDidShowNotification is sent. 
- (void)keyboardWasShown:(NSNotification*)aNotification 
{ 
    // Calculate the frame of the scrollview, in self.view's coordinate system 
    UIScrollView *scrollView = self.scrollView; 
    CGRect scrollViewRect  = [self.view convertRect:scrollView.frame fromView:scrollView.superview]; 

    // Calculate the frame of the keyboard, in self.view's coordinate system 
    NSDictionary* info   = [aNotification userInfo]; 
    CGRect kbRect    = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
    kbRect      = [self.view convertRect:kbRect fromView:nil]; 

    // Figure out where the two frames overlap, and set the content offset of the scrollview appropriately 
    CGRect hiddenScrollViewRect = CGRectIntersection(scrollViewRect, kbRect); 
    if (!CGRectIsNull(hiddenScrollViewRect)) 
    { 
     UIEdgeInsets contentInsets  = UIEdgeInsetsMake(0.0, 0.0, hiddenScrollViewRect.size.height, 0.0); 
     scrollView.contentInset   = contentInsets; 
     scrollView.scrollIndicatorInsets = contentInsets; 
    } 

    [self scrollToActiveTextField]; 
} 

// Called when the UIKeyboardWillHideNotification is sent 
- (void)keyboardWillBeHidden:(NSNotification*)aNotification 
{ 
    self.scrollView.contentInset   = UIEdgeInsetsZero; 
    self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero; 
} 

- (void)scrollToActiveTextField 
{ 
    if (self.activeTextField) 
    { 
     CGRect visibleRect = self.activeTextField.frame; 
     visibleRect  = [self.scrollView convertRect:visibleRect fromView:self.activeTextField.superview]; 
     visibleRect  = CGRectInset(visibleRect, 0.0f, -5.0f); 
     [self.scrollView scrollRectToVisible:visibleRect animated:YES]; 
    } 
} 
+0

Wcześniej próbowałem manipulować ramką przewijania, aby to osiągnąć, ale użycie 'contentInset' znacznie uprościło kod. – chakrit

+0

@chakrit Cieszę się, że to pomogło! – lnafziger

+0

Jeśli wyrywasz sobie włosy, próbując dowiedzieć się, dlaczego scrollRectToVisible nie działa, wydaje się, że Apple coś zmieniło (przynajmniej w przypadku iOS 8 w moim symulatorze), gdzie jeśli rect znajduje się poza ramką treści UITableView, UICollectionView lub UIScrollView, nawet nie próbuje go przewijać. Na przykład, nazwałem [self.activeField convertRect: self.activeField.frame toView: self.tableView], ale powinien to być [self.activeField.superview convertRect: self.activeField.frame toView: self.tableView], więc rect.origin.x miał około 500, czyli> 320, więc nie przewijał. –

0

Ustaw delegata swojego scrollView jako siebie, gdziekolwiek jesteś, przeglądasz w przeglądarce swój kod

((UIScrollView*)self.view).delegate=self; 

następnie

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.view.frame = self.parentViewController.view.frame; 

    [self.textView becomeFirstResponder]; 

    NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width); 

    [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWasShown:) 
              name:UIKeyboardDidShowNotification 
              object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWillHide:) 
              name:UIKeyboardWillHideNotification 
              object:nil]; 
} 

- (void)keyboardWasShown:(NSNotification *)notification 
{ 
    if([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone) { 

     // Step 1: Get the size of the keyboard. 
     CGFloat keyboardHeight = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; 

     // Step 2: Adjust the bottom content inset of your scroll view by the keyboard height. 
     UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0); 
     ((UIScrollView*)self.view).contentInset = contentInsets; 
     ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; 

     ((UIScrollView*)self.view).scrollEnabled=YES; 
    } 
} 

- (void) keyboardWillHide:(NSNotification *)notification { 
    UIEdgeInsets contentInsets = UIEdgeInsetsZero; 
    ((UIScrollView*)self.view).contentInset = contentInsets; 
    ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; 
    [((UIScrollView*)self.view) setContentOffset:CGPointMake(0.0f, 0.0f) animated:TRUE]; 
    ((UIScrollView*)self.view).contentSize = CGSizeMake(((UIScrollView*)self.view).contentSize.width, ((UIScrollView*)self.view).contentSize.height); 
    ((UIScrollView*)self.view).scrollEnabled=NO; 

} 

#pragma mark - set scrollView content position 
-(void)scrollViewToCenterOfScreen:(UIView *)theView 
{ 
    CGFloat theViewY = theView.center.y; 
    CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; 
    CGFloat avaliableHeight = applicationFrame.size.height - 300; 
    CGFloat y = theViewY - avaliableHeight/2.0; 
    if(y<0) 
     y = 0; 
    [((UIScrollView*)self.view) setContentOffset:CGPointMake(0,y) animated:YES]; 
} 

#pragma -mark UITextField Delegate methods 

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 
{ 
    [self scrollViewToCenterOfScreen:textField]; 
    return YES; 
} 

Teraz ustaw delegat swoim polu tekstowym. Ilekroć textFieldShouldBeginEditing: Twój scrollview automatycznie porusza się po tym. scrollViewToCenterOfScreen: metoda ustaw twoją pozycję scrollview na pozycji z tekstem.

Zdecydowanie ustawi twoje wstawki zawartości przewijania, jak również setContentOffset. Daj mi znać, jeśli nadal napotykasz ten problem. Dzięki

+0

Cześć Chandan, problem nie polega na tym, że nie ustawia on wstawek - mogę ustawić je ręcznie. że nie mogę określić odpowiedniej wysokości, aby ustawić je na podstawie innych elementów na ekranie Używam arbitralnej liczby dla wysokości – Kristin

+0

Cześć Kristin, przepraszam za spóźnioną odpowiedź Czy rozwiązałeś już swój problem? wiem, że mogę to wyjaśnić.Dziękuję – chandan

+0

Nie mam - wciąż twardo kodujemy – Kristin