iPhone - biết liệu UIScrollView đạt trên cùng hay dưới cùng


Câu trả lời:


198

Triển khai UIScrollViewDelegatetrong lớp của bạn, rồi thêm cái này:

-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
    float scrollViewHeight = scrollView.frame.size.height;
    float scrollContentSizeHeight = scrollView.contentSize.height;
    float scrollOffset = scrollView.contentOffset.y;

    if (scrollOffset == 0)
    {
        // then we are at the top
    }
    else if (scrollOffset + scrollViewHeight == scrollContentSizeHeight)
    {
        // then we are at the end
    }
}

Hy vọng đây là những gì bạn đang sau! Nếu không có người tinker bằng cách thêm nhiều điều kiện hơn vào đoạn mã trên và NSLog giá trị của scrollOffset.


4
Nếu bạn đang ở trong một navigationController, bạn có thể muốn làm một cái gì đó như thế này: scrollOffset <= (0 - self.navigationController.navigationBar.frame.size.height - 20)(scrollOffset + scrollHeight) >= scrollContentSizeHeight
Wayne

Vấn đề với đó là số lần trả lại ... mọi thứ được gọi hai lần khi đạt đến đỉnh hoặc đáy. Có giải pháp nào cho điều đó, ngoài việc tắt tính năng trả lại bảng hoặc chế độ xem bộ sưu tập?
acceptkov

@denikov bạn đã tìm thấy giải pháp nào cho điều đó chưa?
Priyal

83

Chà, contentInsetscũng có liên quan, khi bạn cố gắng xác định xem scrollView ở trên cùng hay ở cuối. Bạn cũng có thể quan tâm đến các trường hợp khi scrollView của bạn ở trên đầu và dưới cuối. Đây là mã tôi sử dụng để tìm các vị trí trên cùng và dưới cùng:

Nhanh:

extension UIScrollView {

    var isAtTop: Bool {
        return contentOffset.y <= verticalOffsetForTop
    }

    var isAtBottom: Bool {
        return contentOffset.y >= verticalOffsetForBottom
    }

    var verticalOffsetForTop: CGFloat {
        let topInset = contentInset.top
        return -topInset
    }

    var verticalOffsetForBottom: CGFloat {
        let scrollViewHeight = bounds.height
        let scrollContentSizeHeight = contentSize.height
        let bottomInset = contentInset.bottom
        let scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight
        return scrollViewBottomOffset
    }

}

Mục tiêu-C:

@implementation UIScrollView (Additions)

- (BOOL)isAtTop {
    return (self.contentOffset.y <= [self verticalOffsetForTop]);
}

- (BOOL)isAtBottom {
    return (self.contentOffset.y >= [self verticalOffsetForBottom]);
}

- (CGFloat)verticalOffsetForTop {
    CGFloat topInset = self.contentInset.top;
    return -topInset;
}

- (CGFloat)verticalOffsetForBottom {
    CGFloat scrollViewHeight = self.bounds.size.height;
    CGFloat scrollContentSizeHeight = self.contentSize.height;
    CGFloat bottomInset = self.contentInset.bottom;
    CGFloat scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight;
    return scrollViewBottomOffset;
}


@end

Câu trả lời tốt này, thực hiện scrollviewdidscroll có hại cho performences
Vassily

3
Làm cách nào để gọi nó nếu không sử dụng scrollViewDidScroll?
Dave G

2
Vì sự mơ hồ của phép toán dấu phẩy động, tôi đã nhận được "verticalOffsetForBottom" là 1879.05xxx và contentOffset.y của tôi là 1879 khi ở dưới cùng trong Swift 3. Vì vậy, tôi đã đổi return scrollViewBottomOffsetthànhreturn scrollViewBottomOffset.rounded()
chadbag

1
Kể từ iOS 11 safeAreaInsetscũng ảnh hưởng đến nó. scrollView.contentOffset.y + scrollView.bounds.height - scrollView.safeAreaInsets.bottom
InkGolem

35

Nếu bạn muốn mã nhanh chóng:

override func scrollViewDidScroll(scrollView: UIScrollView) {

    if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
        //reach bottom
    }

    if (scrollView.contentOffset.y <= 0){
        //reach top
    }

    if (scrollView.contentOffset.y > 0 && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)){
        //not top and not bottom
    }
}

11

Tiện ích mở rộng đơn giản và rõ ràng:

import UIKit

extension UIScrollView {

    var scrolledToTop: Bool {
        let topEdge = 0 - contentInset.top
        return contentOffset.y <= topEdge
    }

    var scrolledToBottom: Bool {
        let bottomEdge = contentSize.height + contentInset.bottom - bounds.height
        return contentOffset.y >= bottomEdge
    }

}

Trên GitHub:

https://github.com/salutis/swift-scroll-view-edges


4

Tôi đã tìm ra chính xác cách thực hiện:

CGFloat maxPosition = scrollView.contentInset.top + scrollView.contentSize.height + scrollView.contentInset.bottom - scrollView.bounds.size.height;
CGFloat currentPosition = scrollView.contentOffset.y + self.topLayoutGuide.length;

if (currentPosition == maxPosition) {
  // you're at the bottom!
}

0

Làm như thế này (đối với Swift 3):

class MyClass: UIScrollViewDelegate {

   func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
           //scrolled to top, do smth
        }


    }
}

Chào mừng đến với SO! Khi đăng mã trong câu trả lời của bạn, nó là o hữu ích giải thích cách mã của bạn giải quyết vấn đề của OP :)
Joel
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.