프로그래밍 방식으로 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);
그랜트 랜드 씹

70
삽입물을 고려하지 않았습니다. 이 바닥을 선호해야한다고 생각합니다. 오프셋 :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łomiej Semańczyk

1
이것은 하단 삽입을 처리하고 0을 넘어갑니다.let bottomOffsetY = max(collectionView.contentSize.height - collectionView.bounds.height + collectionView.contentInset.bottom, 0)
감각적

136

쉬운 복사 붙여 넣기를 위해 허용되는 답변의 신속한 버전 :

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

3
bottomOffset은 예제에서 var가 아니어야합니다.
Tige Hobbes the Octge

사실, 그것을 바꿨다. swift2 stuff :)
Esqarrouth

9
scrollView.bounds.size.height> 0, 그렇지 않으면 당신은 이상한 결과를해야합니다 - scrollView.contentSize.height가 있는지 확인할 필요가
iluvatar_GR

2
이 솔루션은 새로운 탐색 표시 줄이있을 때 완벽하지 않습니다.
스위프트 래빗

@Josh, 아직도 하루를 기다리는 그래서 SO는 이것에 대해 알아
Alexandre G

53

가장 간단한 해결책 :

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

감사. 스크롤보기를 UITableView로 변경하는 것을 잊어 버렸고이 코드는 UITableView에서도 작동했습니다.
LevinsonTechnologies

1
왜 안될까요 : [scrollview scrollRectToVisible : CGRectMake (0, scrollview.contentSize.height, 1, 1) animated : YES];
Johannes

29

기존 답변을 개선 한 것입니다.

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

하단 삽입도 처리합니다 (키보드를 볼 때 스크롤보기를 조정하는 데 사용하는 경우)


이것은 정답이어야합니다 ... 키보드 팝업이 있으면 깨질 수있는 다른 것은 아닙니다.
벤 길드

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

1
그렇지 if (sv.contentOffset.y + csz.height > bsz.height) {않습니까?
i_am_jorf

@jeffamaphone-문의 해 주셔서 감사합니다. 실제로이 시점에서 나는 그 상태가 어떤 목적을 달성해야하는지 확신조차하지 못한다! 그것은의 setContentOffset:중요 명령.
matt

아무것도하지 않을 경우 setContentOffset 호출을 피하는 것으로 가정합니까?
i_am_jorf

@jeffamaphone-장치 회전 후 스크롤보기가 내용의 하단이 프레임의 하단보다 높은 것으로 끝날 수있었습니다 (스크롤보기를 회전하면 내용 오프셋이 일정하게 유지되지만 스크롤보기 높이가 커질 수 있기 때문에) 자동 크기 조정). 조건은 다음과 같습니다.이 경우 콘텐츠 하단을 프레임 하단에 다시 내려 놓습니다. 그러나 코드에 붙여 넣을 때 조건을 포함시키는 것은 어리석은 일이었습니다. 그러나 조건 테스트 대상을 올바르게 테스트하고 있습니다.
matt

19

신속한 구현 :

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)

15

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스크롤하기 전에 확인하고 싶을 수도 있습니다.


14

어떤 경우에하는 것은 contentSize보다 낮은bounds ?

스위프트의 경우 :

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

참고로, 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)
  • 목표 -C
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.adjustedContentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
  • 스위프트 확장 (원본을 유지 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

(선택 사항) footerViewcontentInset을 사용하면 솔루션은 다음과 같습니다.

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

가로 ScrollView의 경우

가로 스크롤보기가 있고 끝으로 스크롤하려면 (내 경우에는 가장 오른쪽으로) 수락 된 답변의 일부를 변경해야합니다.

목표 -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

내가 그것을 사용하려고 할 때, 나를 위해 작동하지 않았 UITableViewControllerself.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

scrollToBottom 메소드를 추가하려면 UIScrollView를 확장하십시오.

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.