UIScrollView scroll to bottom programmatically

2019-01-04 05:22发布

How can I make a UIScrollView scroll to the bottom within my code? Or in a more generic way, to any point of a subview?

24条回答
Luminary・发光体
2楼-- · 2019-01-04 05:41

Just an enhancement to the existing answer.

CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];

It takes care of the bottom inset as well (in case you're using that to adjust your scroll view when the keyboard is visible)

查看更多
\"骚年 ilove
3楼-- · 2019-01-04 05:41

I found that contentSize doesn't really reflect the actual size of the text, so when trying to scroll to the bottom, it will be a little bit off. The best way to determine the actual content size is actually to use the NSLayoutManager's usedRectForTextContainer: method:

UITextView *textView;
CGSize textSize = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size;

To determine how much text actually is shown in the UITextView, you can calculate it by subtracting the text container insets from the frame height.

UITextView *textView;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textViewHeight = textView.frame.size.height - textInsets.top - textInsets.bottom;

Then it becomes easy to scroll:

// if you want scroll animation, use contentOffset
UITextView *textView;
textView.contentOffset = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);

// if you don't want scroll animation
CGRect scrollBounds = textView.bounds;
scrollBounds.origin = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);
textView.bounds = scrollBounds;

Some numbers for reference on what the different sizes represent for an empty UITextView.

textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)
查看更多
The star\"
4楼-- · 2019-01-04 05:42

I also found another useful way of doing this in the case you are using a UITableview (which is a subclass of UIScrollView):

[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
查看更多
做自己的国王
5楼-- · 2019-01-04 05:42

In swift:

   if self.mainScroll.contentSize.height > self.mainScroll.bounds.size.height {
        let bottomOffset = CGPointMake(0, self.mainScroll.contentSize.height - self.mainScroll.bounds.size.height);
        self.mainScroll.setContentOffset(bottomOffset, animated: true)
    }
查看更多
姐就是有狂的资本
6楼-- · 2019-01-04 05:43

Swift version of the accepted answer for easy copy pasting:

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)
查看更多
Luminary・发光体
7楼-- · 2019-01-04 05:43

Setting the content offset to the height of the content size is wrong: it scrolls the bottom of the content to the top of the scroll view, and thus out of sight.

The correct solution is to scroll the bottom of the content to the bottom of the scroll view, like this (sv is the UIScrollView):

CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
if (sv.contentOffset.y + bsz.height > csz.height) {
    [sv setContentOffset:CGPointMake(sv.contentOffset.x, 
                                     csz.height - bsz.height) 
                animated:YES];
}
查看更多
登录 后发表回答