330

如何UIScrollView在我的代码中滚动到底部?或者以更通用的方式,到子视图的任何一点?

4

30 回答 30

675

您可以使用 UIScrollView 的setContentOffset:animated:功能滚动到内容视图的任何部分。假设您的 scrollView 是,这里有一些会滚动到底部的代码self.scrollView

目标-C:

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

迅速:

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)

希望有帮助!

于 2009-06-04T19:58:17.213 回答
153

接受答案的 Swift 版本,便于复制粘贴:

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)
于 2015-04-02T11:49:31.420 回答
54

最简单的解决方案:

[scrollview scrollRectToVisible:CGRectMake(scrollview.contentSize.width - 1,scrollview.contentSize.height - 1, 1, 1) animated:YES];
于 2014-03-07T08:41:02.167 回答
30

一个快速的实现:

extension UIScrollView {
   func scrollToBottom(animated: Bool) {
     if self.contentSize.height < self.bounds.size.height { return }
     let bottomOffset = CGPoint(x: 0, y: self.contentSize.height - self.bounds.size.height)
     self.setContentOffset(bottomOffset, animated: animated)
  }
}

用它:

yourScrollview.scrollToBottom(animated: true)
于 2016-07-06T10:32:00.727 回答
28

只是对现有答案的增强。

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

它还负责底部插图(如果您在键盘可见时使用它来调整滚动视图)

于 2013-09-06T11:33:51.363 回答
19

将内容偏移设置为内容大小的高度是错误的:它将内容的底部滚动到滚动视图的顶部,因此看不见。

正确的解决方法是将内容的底部滚动到滚动视图的底部,像这样(sv是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];
}
于 2011-06-11T17:32:57.990 回答
16

Swift 2.2 解决方案,考虑contentInset

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)

这应该在扩展中

extension UIScrollView {

  func scrollToBottom() {
    let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + contentInset.bottom)
    setContentOffset(bottomOffset, animated: true)
  }
}

请注意,您可能需要bottomOffset.y > 0在滚动之前检查是否

于 2016-07-07T09:27:07.650 回答
15

如果contentSize低于bounds怎么办?

对于 Swift 它是:

scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
于 2016-01-16T19:56:25.167 回答
13

滚动到顶部

- CGPoint topOffset = CGPointMake(0, 0);
- [scrollView setContentOffset:topOffset animated:YES];

滚动到底部

- CGPoint bottomOffset = CGPointMake(0, scrollView.contentSize.height - self.scrollView.bounds.size.height);
 - [scrollView setContentOffset:bottomOffset animated:YES];
于 2012-02-17T09:40:08.227 回答
8

看起来这里的所有答案都没有考虑到安全区域。从 iOS 11 开始,iPhone X 引入了安全区域。这可能会影响 scrollView 的contentInset.

对于 iOS 11 及更高版本,正确滚动到包含内容插图的底部。您应该使用adjustedContentInset而不是contentInset. 检查此代码:

  • 迅速:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.adjustedContentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
  • Objective-C
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.adjustedContentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
  • Swift 扩展(保留原来的contentOffset.x):
extension UIScrollView {
    func scrollsToBottom(animated: Bool) {
        let bottomOffset = CGPoint(x: contentOffset.x,
                                   y: contentSize.height - bounds.height + adjustedContentInset.bottom)
        setContentOffset(bottomOffset, animated: animated)
    }
}

参考:

于 2019-08-07T20:55:35.810 回答
7

在您使用 UITableview(它是 UIScrollView 的子类)的情况下,我还发现了另一种有用的方法:

[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
于 2009-06-05T15:35:55.697 回答
7

在 Swift 中使用 UIScrollView 的setContentOffset:animated:函数滚动到底部。

let bottomOffset : CGPoint = CGPointMake(0, scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
于 2016-01-15T15:15:03.927 回答
6

使用(可选)footerViewcontentInset,解决方案是:

CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height - tableView.frame.size.height + _tableView.contentInset.bottom);
if (bottomOffset.y > 0) [_tableView setContentOffset: bottomOffset animated: YES];
于 2012-01-28T19:59:30.467 回答
6

如果您以某种方式更改 scrollView contentSize(例如,向 scrollView 内的 stackView 添加一些内容),您必须scrollView.layoutIfNeeded()在滚动之前调用,否则它什么也不做。

例子:

scrollView.layoutIfNeeded()
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
if(bottomOffset.y > 0) {
    scrollView.setContentOffset(bottomOffset, animated: true)
}
于 2019-11-14T13:47:20.840 回答
6

迅速:

你可以使用这样的扩展:

extension UIScrollView {
    func scrollsToBottom(animated: Bool) {
        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
        setContentOffset(bottomOffset, animated: animated)
    }
}

采用:

scrollView.scrollsToBottom(animated: true)
于 2019-12-28T15:22:43.457 回答
3

valdyr,希望这会对你有所帮助:

CGPoint bottomOffset = CGPointMake(0, [textView contentSize].height - textView.frame.size.height);

if (bottomOffset.y > 0)
 [textView setContentOffset: bottomOffset animated: YES];
于 2010-10-29T07:41:05.137 回答
3

类别来救援!

将此添加到某处的共享实用程序标头中:

@interface UIScrollView (ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated;
@end

然后到那个实用程序实现:

@implementation UIScrollView(ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated
{
     CGPoint bottomOffset = CGPointMake(0, self.contentSize.height - self.bounds.size.height);
     [self setContentOffset:bottomOffset animated:animated];
}
@end

然后在任何你喜欢的地方实现它,例如:

[[myWebView scrollView] scrollToBottomAnimated:YES];
于 2013-03-14T19:18:49.697 回答
3

对于水平滚动视图

如果你喜欢我有一个 Horizo​​ntal ScrollView 并且想要滚动到它的末尾(在我的例子中是它的最右边),你需要更改已接受答案的某些部分:

Objective-C

CGPoint rightOffset = CGPointMake(self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, 0 );
[self.scrollView setContentOffset:rightOffset animated:YES];

迅速

let rightOffset: CGPoint = CGPoint(x: self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, y: 0)
self.scrollView.setContentOffset(rightOffset, animated: true)
于 2019-07-07T08:22:10.420 回答
1

确保内容底部可见的一个好方法是使用以下公式:

contentOffsetY = MIN(0, contentHeight - boundsHeight)

这可确保您的内容的底部边缘始终位于或高于视图的底部边缘。这MIN(0, ...)是必需的,因为UITableView(并且可能UIScrollView)确保contentOffsetY >= 0用户何时尝试通过明显捕捉来滚动contentOffsetY = 0。这对用户来说看起来很奇怪。

实现这一点的代码是:

UIScrollView scrollView = ...;
CGSize contentSize = scrollView.contentSize;
CGSize boundsSize = scrollView.bounds.size;
if (contentSize.height > boundsSize.height)
{
    CGPoint contentOffset = scrollView.contentOffset;
    contentOffset.y = contentSize.height - boundsSize.height;
    [scrollView setContentOffset:contentOffset animated:YES];
}
于 2013-03-27T08:34:05.903 回答
1

如果您不需要动画,则可以使用:

[self.scrollView setContentOffset:CGPointMake(0, CGFLOAT_MAX) animated:NO];
于 2014-01-16T15:44:28.153 回答
1

虽然Matt解决方案对我来说似乎是正确的,但如果已经设置了集合视图插图,您还需要考虑集合视图插图。

修改后的代码将是:

CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
NSInteger bottomInset = sv.contentInset.bottom;
if (sv.contentOffset.y + bsz.height + bottomInset > csz.height) {
    [sv setContentOffset:CGPointMake(sv.contentOffset.x, 
                                     csz.height - bsz.height + bottomInset) 
                animated:YES];
}
于 2014-06-17T14:09:27.620 回答
1

迅速:

   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)
    }
于 2015-09-24T20:37:06.717 回答
1

滚动到表格视图的最后一项的解决方案:

斯威夫特 3:

if self.items.count > 0 {
        self.tableView.scrollToRow(at:  IndexPath.init(row: self.items.count - 1, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
}
于 2017-02-28T20:18:11.523 回答
0

对我不起作用,当我尝试在UITableViewControlleron中使用它时self.tableView (iOS 4.1),添加footerView. 它滚动出边界,显示黑屏。

替代解决方案:

 CGFloat height = self.tableView.contentSize.height; 

 [self.tableView setTableFooterView: myFooterView];
 [self.tableView reloadData];

 CGFloat delta = self.tableView.contentSize.height - height;
 CGPoint offset = [self.tableView contentOffset];
 offset.y += delta;

 [self.tableView setContentOffset: offset animated: YES];
于 2010-10-27T12:55:32.740 回答
0
CGFloat yOffset = scrollView.contentOffset.y;

CGFloat height = scrollView.frame.size.height;

CGFloat contentHeight = scrollView.contentSize.height;

CGFloat distance = (contentHeight  - height) - yOffset;

if(distance < 0)
{
    return ;
}

CGPoint offset = scrollView.contentOffset;

offset.y += distance;

[scrollView setContentOffset:offset animated:YES];
于 2014-01-31T08:23:08.400 回答
0

我发现这contentSize并不能真正反映文本的实际大小,所以当试图滚动到底部时,它会有点偏离。确定实际内容大小的最佳方法实际上是使用NSLayoutManager'usedRectForTextContainer:方法:

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

要确定 中实际显示了多少文本UITextView,您可以通过从框架高度中减去文本容器插入来计算它。

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

然后滚动变得很容易:

// 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;

一些数字供参考,以了解不同尺寸代表空的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)
于 2015-06-26T22:00:14.097 回答
0

扩展 UIScrollView 以添加一个 scrollToBottom 方法:

extension UIScrollView {
    func scrollToBottom(animated:Bool) {
        let offset = self.contentSize.height - self.visibleSize.height
        if offset > self.contentOffset.y {
            self.setContentOffset(CGPoint(x: 0, y: offset), animated: animated)
        }
    }
}
于 2020-04-26T04:41:08.347 回答
0

要滚动到底端,我们必须使用目标视图的最大高度。

import UIKit

extension UIScrollView {

    func scrollToBottomOf(targetView: UIView, animated: Bool) {
        setContentOffset(CGPoint(x:targetView.frame.minX, y:targetView.frame.maxY), animated: animated)
    }
}

//func invocation example 
optionScrollView.scrollToBottomOf(targetView: self.optionsStackView, animated: false)
于 2021-11-09T04:52:49.293 回答
-1

接受答案的Xamarin.iOS版本,UICollectionView便于复制和粘贴

var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);          
CollectionView.SetContentOffset (bottomOffset, false);
于 2018-08-10T03:49:31.553 回答
-2

Xamarin.iOS版本的已接受答案

var bottomOffset = new CGPoint (0,
     scrollView.ContentSize.Height - scrollView.Frame.Size.Height
     + scrollView.ContentInset.Bottom);

scrollView.SetContentOffset (bottomOffset, false);
于 2018-08-10T03:41:47.430 回答