プログラムでUIScrollViewを下にスクロール


298

UIScrollViewコード内で一番下までスクロールするにはどうすればよいですか?または、より一般的な方法で、サブビューの任意のポイントに?

回答:


626

UIScrollViewのsetContentOffset:animated:関数を使用して、コンテンツビューの任意の部分にスクロールできます。scrollViewがself.scrollView次のようであると想定して、下にスクロールするコードをいくつか示します。

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

お役に立てば幸いです。


25
おそらく、スクロールビューからではなく、下にスクロールするには、次のようにします。CGPoint bottomOffset = CGPointMake(0、[self.scrollView contentSize] .height-self.scrollView.frame.size.height);
Grantland Chew

70
あなたはインセットを考慮に入れていません。私はあなたはこのbottomOffsetを好むべきだと思います:CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
Martin

1
これはランドスケープモードでは機能しません。完全に下までスクロールしない
Mo Farhand

1
contentSize未満の場合、正常に動作しませんbounds。したがって、次のようになります。scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
BartłomiejSemańczyk16年1

1
このハンドル下のインセット、および0を超えて行く:let bottomOffsetY = max(collectionView.contentSize.height - collectionView.bounds.height + collectionView.contentInset.bottom, 0)
Senseful

136

コピーを簡単に貼り付けるための承認済み回答のSwiftバージョン:

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

3
あなたの例では、bottomOffsetをvarではなくletにする必要があります。
Tigeを

本当、それを変えた。swift2のもの:)
Esqarrouth

9
scrollView.contentSize.height-scrollView.bounds.size.height> 0かどうかを確認する必要があります。それ以外の場合は、より奇妙な結果になります
iluvatar_GR

2
新しいナビゲーションバーを使用している場合、このソリューションは完璧ではありません。
Swift Rabbit

@ジョシュ、それでもSOがこれについて知る日を待っている
Alexandre G

53

最も簡単なソリューション:

[scrollview scrollRectToVisible:CGRectMake(scrollview.contentSize.width - 1,scrollview.contentSize.height - 1, 1, 1) animated:YES];

ありがとう。scrollviewをUITableViewに変更するのを忘れており、このコードは、FUIのUITableViewでも機能しました。
LevinsonTechnologies

1
なぜだけではない:[scrollview scrollRectToVisible:CGRectMake(0、scrollview.contentSize.height、1、1)animated:YES];
ヨハネス

29

既存の回答を拡張しただけです。

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

下部のインセットも処理します(キーボードが表示されているときにスクロールビューを調整するためにそれを使用している場合)


これは正解でなければなりません...キーボードポップアップが表示されても壊れてしまう他の問題ではありません。
ベン・ギルド

20

迅速な実装:

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)

19

コンテンツのオフセットをコンテンツサイズの高さに設定するのは誤りです。コンテンツの下部をスクロールビューの上部にスクロールするため、見えなくなります。

正しい解決策は、次のようにコンテンツの下部をスクロールビューの下部にスクロールすることです(svUIScrollViewです)。

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];
}

1
そうじゃないのif (sv.contentOffset.y + csz.height > bsz.height) {
i_am_jorf

@jeffamaphone-お問い合わせいただきありがとうございます。実際には、この時点では、条件がどのような目的で使用されるはずだったのかさえわかりません!setContentOffset:重要なのはコマンドです。
マット

何もしない場合は、setContentOffset呼び出しを回避すると思いますか?
i_am_jorf

@jeffamaphone-以前は、デバイスの回転後、コンテンツの下部がフレームの下部よりも高い状態でスクロールビューが終了する可能性がありました(スクロールビューを回転した場合、コンテンツのオフセットは一定のままですが、スクロールビューの高さが大きくなる可能性があるためです)自動サイズ変更)。条件は次のとおりです。それが発生した場合は、コンテンツをフレームの下部に戻します。しかし、コードに貼り付けたときの状態を含めるのはばかげたことでした。ただし、条件それがテストしていたものを正しくテストしています。
マット

15

contentInset考慮に入れられたSwift 2.2ソリューション

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スクロールする前に、


14

contentSizeより低い場合はどうなりboundsますか?

Swiftの場合:

scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)

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

7

UITableview(UIScrollViewのサブクラス)を使用している場合に、これを行う別の便利な方法も見つけました。

[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

FYI、唯一のUITableView機能だ
OhadM

7

UIScrollViewのsetContentOffset:animated:関数を使用して、Swiftで一番下までスクロールします。

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

5

ここでのすべての回答では、安全な領域が考慮されていなかったようです。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)
    }
}

参照:


5

(オプション)footerViewとを使用するcontentInsetと、解決策は次のとおりです。

CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height - tableView.frame.size.height + _tableView.contentInset.bottom);
if (bottomOffset.y > 0) [_tableView setContentOffset: bottomOffset animated: YES];

4

迅速:

次のような拡張機能を使用できます。

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)

3

valdyr、これがあなたに役立つことを願っています:

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

if (bottomOffset.y > 0)
 [textView setContentOffset: bottomOffset animated: YES];

2

救助へのカテゴリー!

これを共有ユーティリティのヘッダーのどこかに追加します。

@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];

常に、常に、常に、常にカテゴリを使用してください!完璧:)
Fattie

2

水平スクロールビューの場合

私のような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)

2

どういうわけか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)
}

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];
}


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];
}

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)
    }

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)
}

0

追加後、UITableViewControllerで使用しようとしたところ、うまくいきませんでした。枠の外にスクロールして、黒い画面を表示します。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];

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

0

contentSizeテキストの実際のサイズを実際には反映していないことがわかったので、下にスクロールしようとすると、少しずれます。実際のコンテンツサイズを決定する最良の方法は、実際にはNSLayoutManagerusedRectForTextContainer:メソッドを使用することです。

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)

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)
        }
    }
}

これは既存の回答に何を追加しますか?
greybeard

-1

受け入れられた回答のXamarin.iOSバージョン

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

scrollView.SetContentOffset (bottomOffset, false);

-1

UICollectionViewコピーと貼り付けを簡単にするための承認済み回答のXamarin.iOSバージョン

var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);          
CollectionView.SetContentOffset (bottomOffset, false);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.