Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView's content offset being reset

I have been struggling for a long time with a problem with a UIScrollView.

I have a UIScrollVIew that contains a UITextView as a subview. When I select the text view a keyboard pops up. I want to resize the text view to fit exactly in the available space, and also scroll the scroll view so that the text view is positioned exactly in the visible space (not hidden by the keyboard).

When the keyboard appears I call a method that calculates the appropriate size for the text view and then performs the following code:

[UIView animateWithDuration:0.3 
                 animations:^
 { 
     self.textView.frame = frame;
 }  
 ];

[self.scrollView setContentOffset:CGPointMake(0,frame.origin.y) animated:YES];

(here frame is the appropriate frame for the text view).

Unfortunately the scroll view does not always scroll to the correct position, especially when it is already at a non zero vertical content offset when I select the text view. I know that the content offset that I'm setting it to is correct.

After a lot of testing I finally realized that what was happening was that after the animation completed, the scroll view was automatically scrolling again.

This code does work:

UIView animateWithDuration:0.3 
                 animations:^
 { 
     self.textView.frame = frame;
 }
 completion:^(BOOL finished) {
     [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
 }
 ];

but it looks strange because the scroll view scrolls to the wrong position, then to the right one.

Does anyone know how I can prevent the scroll view from changing it's content offset when the text view frame finishes its animation?

I am testing using iOS 5.0.


Here is a solution that I found that works. I'm still don't completely understand what's happening, possible it has something to do with the way my springs and struts are set. Basically I am shrinking the scroll view content size by the same amount that the text view shrinks.

- (void)keyboardDidShow:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];

    // Get the height of the keyboard
    CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    kbRect = [self.view convertRect:kbRect fromView:nil];
    CGSize kbSize = kbRect.size;

    // Adjust the height of the text view to fit in the visible view
    CGRect frame = self.textView.frame;
    int visibleHeight = self.view.frame.size.height;
    visibleHeight -= kbSize.height;
    frame.size.height = visibleHeight;

    // Get the new scroll view content size
    CGSize contentSize = self.scrollView.contentSize;
    contentSize.height = contentSize.height - self.textView.frame.size.height + frame.size.height;

    [UIView animateWithDuration:0.1 
                     animations:^
     { 
         self.textView.frame = frame;
         // Note that the scroll view content size needs to be reset, or the scroll view
         // may automatically scroll to a new position after the animation is complete.
         self.scrollView.contentSize = contentSize;
         [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
     }     
     ];

    // Turn off scrolling in scroll view
    self.scrollView.scrollEnabled = NO;
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    // Update the view layout
    [UIView animateWithDuration:0.3 animations:^
     {
         self.scrollView.contentOffset = CGPointZero;
         [self updateViewLayout];
     }
     ];

    // Turn on scrolling in the scroll view
    self.scrollView.scrollEnabled = YES;
}

([self updateViewLayout] is a method that returns the text view to the correct height, and resets the scroll view content size, as well as making sure all the other subviews are properly positioned).

like image 421
Darren Avatar asked Feb 22 '23 12:02

Darren


1 Answers

Do not adjust the frame of the text view. All you need to do is scroll the scrollview. If you scroll the scrollview animated, then the textView will slide up animated. Just do the following:

[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];

If you need the scroll view to scroll at a specific rate then manually adjust the content offset in an animation block.(I haven't tested this, you may want to adjust the animation flag, or step through the content offset one pixel at a time if this doesn't work)

[UIView animateWithDuration:0.3f 
             animations:^{ 
  [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
} ];
like image 148
Jack Freeman Avatar answered Mar 05 '23 14:03

Jack Freeman