Nhận UIScrollView để cuộn lên đầu


Câu trả lời:


316

CẬP NHẬT CHO iOS 7

[self.scrollView setContentOffset:
    CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];

NGUYÊN

[self.scrollView setContentOffset:CGPointZero animated:YES];

hoặc nếu bạn muốn duy trì vị trí cuộn ngang và chỉ cần đặt lại vị trí dọc:

[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
    animated:YES];

50
Nếu bạn đang làm điều này cho iOS 7 UIScrollView contentInset, thật không may , bạn có thể phải tính đến điều đó. [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];thực hiện công việc cho tôi
runmad

11
Tôi đã có thể cuộn lên trên cùng, ngay bên dưới thanh điều hướng và trạng thái. [scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];Nó hoạt động trong iOS 6 & 7
Amozoss 28/12/13

Điều này không hiệu quả với tôi, có lẽ bởi vì tôi đang làm điều gì đó điên rồ với một cái nhìn ngược trong bộ sprite. Nhưng nếu bất cứ ai khác cũng điên rồ như tôi - và mặc định cuộn của bạn ở dưới cùng - điều này sẽ cuộn nó lên trên cùng:[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
GilesDMiddleton

Nhận xét vào cuối ngày: bạn nên điều chỉnh cho nội dung được chèn bất kể phiên bản HĐH. iOS 7 tình cờ sử dụng nó để cho phép cuộn nội dung bên dưới thanh trạng thái nhưng nó luôn được hiển thị như một tài sản, do đó luôn được ai đó sử dụng.
Tommy

2
Đối với iOS 11+, câu trả lời của Jakub Truhlář bên dưới bằng cách sử dụng điều chỉnhContentInset là hữu ích, ít nhất là trong trường hợp của tôi.
tnev

61

Đây là một tiện ích mở rộng Swift giúp dễ dàng:

extension UIScrollView {
    func scrollToTop() {
        let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
        setContentOffset(desiredOffset, animated: true)
   }
}

Sử dụng:

myScrollView.scrollToTop()

40

iOS 11 trở lên

cố gắng làm việc với các mới adjustedContentInset.

Ví dụ: (cuộn lên trên cùng):

var offset = CGPoint(
    x: -scrollView.contentInset.left, 
    y: -scrollView.contentInset.top)

if #available(iOS 11.0, *) {
    offset = CGPoint(
        x: -scrollView.adjustedContentInset.left, 
        y: -scrollView.adjustedContentInset.top)    
}

scrollView.setContentOffset(offset, animated: true)

Ngay cả khi bạn sử dụng prefersLargeTitles, safe areavv



23

Sử dụng setContentOffset:animated:

[scrollView setContentOffset:CGPointZero animated:YES];

17

Trả lời cho Swift 2.0 / 3.0 / 4.0 và iOS 7+:

let desiredOffset = CGPoint(x: 0, y: -self.scrollView.contentInset.top)
self.scrollView.setContentOffset(desiredOffset, animated: true)

8

Trong iOS7, tôi gặp khó khăn khi đưa một chế độ xem cụ thể lên đầu, hoạt động trong iOS6 và đã sử dụng tính năng này để đặt chế độ xem cuộn lên trên cùng.

[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];

Tôi có vấn đề tương tự trong iOS7. Có ai biết cách kích hoạt tính năng này cho UITableView không?
DZenBot

1
Thật buồn cười khi cách này hoạt động khi hoạt hình là KHÔNG, nhưng không phải khi hoạt hình là CÓ. Nếu CÓ, thì nó sẽ cuộn gần như topdevgm16
Matt Becker


2

Để sao chép hoàn toàn hành vi scrollToTop của thanh trạng thái, chúng ta không chỉ phải thiết lập nội dung Offerset mà còn muốn đảm bảo các cuộn cuộn được hiển thị. Nếu không, người dùng có thể nhanh chóng bị lạc.

Phương pháp công khai duy nhất để thực hiện điều này là flashScrollIndicators. Thật không may, gọi nó một lần sau khi thiết lập nội dung Offerset không có hiệu lực vì nó được đặt lại ngay lập tức. Tôi tìm thấy nó hoạt động khi làm flash mỗi lần trong scrollViewDidScroll:.

// define arbitrary tag number in a global constants or in the .pch file
#define SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG 19291

- (void)scrollContentToTop {
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];

    self.scrollView.tag = SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.scrollView.tag = 0;
    });
}

Trong UIScrollViewDelegate của bạn (hoặc UITable / UICollectionViewDelegate) thực hiện điều này:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
        [scrollView flashScrollIndicators];
    }
}

Độ trễ ẩn ngắn hơn một chút so với hành vi scrollToTop trên thanh trạng thái nhưng trông vẫn rất đẹp.

Lưu ý rằng tôi đang lạm dụng thẻ xem để giao tiếp trạng thái "isScrollingToTop" vì tôi cần điều này trên các bộ điều khiển xem. Nếu bạn đang sử dụng thẻ cho một thứ khác, bạn có thể muốn thay thế thẻ này bằng iVar hoặc thuộc tính.


Tôi chưa thử nghiệm, nhưng nó sẽ ném cái này vào runloop tiếp theo nếu bạn chỉ sử dụng DISPATCH_TIME_NOW thay thế. Cảm ơn vì đã làm công việc này, không chắc tôi cần nó, nhưng tốt để biết.
Dan Rosenstark

Cách đây một thời gian và tôi không nhớ chính xác nhưng tôi tin rằng điều này không hiệu quả. Trì hoãn đến lần chạy tiếp theo thường là điều đầu tiên tôi thử trong những trường hợp như vậy.
Ortwin Gentz

2

Tôi nghĩ rằng tôi có một câu trả lời phải tương thích hoàn toàn với iOS 11 cũng như các phiên bản trước (để cuộn dọc)

Điều này sẽ tính đến điều chỉnhContentInset mới và cũng tính đến phần bù bổ sung cần thiết khi preLaveTitleTitle trên navigationBar, có vẻ như yêu cầu bù thêm 52px ở trên bất kỳ giá trị mặc định nào

Điều này hơi khó khăn vì điều chỉnhContentInset thay đổi tùy thuộc vào trạng thái titleBar (tiêu đề lớn so với tiêu đề nhỏ) vì vậy tôi cần kiểm tra và xem chiều cao của titleBar là gì và không áp dụng bù 52px nếu nó đã ở trạng thái lớn. Không thể tìm thấy bất kỳ phương pháp nào khác để kiểm tra trạng thái của navigationBar vì vậy nếu có ai có tùy chọn tốt hơn là xem chiều cao có> 44.0 tôi muốn nghe không

func scrollToTop(_ scrollView: UIScrollView, animated: Bool = true) {
    if #available(iOS 11.0, *) {
        let expandedBar = (navigationController?.navigationBar.frame.height ?? 64.0 > 44.0)
        let largeTitles = (navigationController?.navigationBar.prefersLargeTitles) ?? false
        let offset: CGFloat = (largeTitles && !expandedBar) ? 52: 0
        scrollView.setContentOffset(CGPoint(x: 0, y: -(scrollView.adjustedContentInset.top + offset)), animated: animated)
    } else {
        scrollView.setContentOffset(CGPoint(x: 0, y: -scrollView.contentInset.top), animated: animated)
    }
}

Lấy cảm hứng từ giải pháp của Jakub


2

Điều này rất phổ biến khi thanh điều hướng của bạn chồng lên phần nhỏ của nội dung scrollView và có vẻ như nội dung bắt đầu không phải từ đầu. Để sửa nó, tôi đã làm 2 việc:

  • Trình kiểm tra kích thước - Chế độ xem cuộn - Nội dung -> Thay đổi từ Tự động thành Không bao giờ.
  • Trình kiểm tra kích thước - Ràng buộc - "Align Top to" (Ràng buộc liên kết trên cùng) - Mục thứ hai -> Thay đổi từ Superview.Top thành Safe Area.Topgiá trị (trường không đổi) được đặt thành 0

Nội dung - Không bao giờ Căn chỉnh ScrolView.Top đến Khu vực an toàn.Top


1

Di chuyển đến đầu trang cho UITableViewController, UICollectionViewControllerhoặc bất kỳ UIViewControllerUIScrollView

extension UIViewController {

  func scrollToTop(animated: Bool) {
    if let tv = self as? UITableViewController {
        tv.tableView.setContentOffset(CGPoint.zero, animated: animated)
    } else if let cv = self as? UICollectionViewController{
        cv.collectionView?.setContentOffset(CGPoint.zero, animated: animated)
    } else {
        for v in view.subviews {
            if let sv = v as? UIScrollView {
                sv.setContentOffset(CGPoint.zero, animated: animated)
            }
        }
    }
  }
}

0

Trong SWIFT 5 Chỉ cần đặt Offset nội dung về 0

scrollView.setContentOffset(CGPoint.zero, animated: true)

-4

Tôi đã thử tất cả các cách. Nhưng không có gì làm việc cho tôi. Cuối cùng tôi đã làm như thế này.

Tôi đã thêm self.view .addSubview(self.scroll)dòng mã trong viewDidLoad. Sau khi bắt đầu thiết lập khung cho chế độ xem cuộn và thêm các thành phần vào chế độ xem cuộn.

Nó làm việc cho tôi.

Hãy chắc chắn rằng bạn đã thêm self.view .addSubview(self.scroll)dòng vào đầu. sau đó bạn có thể thêm các yếu tố UI.


Hãy xóa cái này. Mặc dù nó chắc chắn có ý nghĩa vào thời điểm đó, các vấn đề phân cấp quan điểm của bạn không liên quan đến câu hỏi này.
Dan Rosenstark

1
@Cristik nếu chế độ xem cuộn của bạn không nằm trong hệ thống phân cấp chế độ xem hoặc máy tính của bạn bị tắt, tất nhiên không cái nào trong số này hoạt động. Nhưng OP đã hỏi một điều khá hẹp
Dan Rosenstark
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.