UITableView - cuộn lên trên cùng


393

Trong chế độ xem bảng của tôi, tôi phải cuộn lên trên cùng. Nhưng tôi không thể đảm bảo rằng đối tượng đầu tiên sẽ là phần 0, hàng 0. Có thể là chế độ xem bảng của tôi sẽ bắt đầu từ phần số 5.

Vì vậy, tôi nhận được một ngoại lệ, khi tôi gọi:

[mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

Có cách nào khác để cuộn lên đầu bảng xem không?

Câu trả lời:


857

UITableView là một lớp con của UIScrollView, vì vậy bạn cũng có thể sử dụng:

[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

Hoặc là

[mainTableView setContentOffset:CGPointZero animated:YES];

Và trong Swift:

mainTableView.setContentOffset(CGPointZero, animated:true)

Và trong Swift 3 trở lên:

mainTableView.setContentOffset(.zero, animated: true)

9
Lần đầu tiên tôi đã thử điều này với CGRectZero, tương đương với CGRectMake (0, 0, 0, 0). Điều này không hoạt động, nhưng kỳ lạ ở trên không. Tôi đoán nó cần một chiều rộng và chiều cao tích cực. Cảm ơn bạn.
Keller

5
Lưu ý, bạn sẽ muốn hoạt hình: KHÔNG nếu bạn chạy cái này trong scrollToRowAtIndexPath: để làm cho bảng bắt đầu ở đúng vị trí. Hy vọng nó giúp!
Fattie

3
@ hasan83 CGRectMake (0, 0, 0, 0) hoặc CGRectZero không phải là một chỉnh lưu có thể nhìn thấy. Tôi cũng sẽ nói rằng [mainTableView setContent Offerset: CGPointZero hoạt hình: CÓ]; là biểu hiện đẹp hơn.
catlan

8
có ai để ý rằng trong iOS11 tất cả đều bị hỏng và không cuộn đúng cách trong một số trường hợp không?
Peter Lapisu

11
@PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)dường như hoạt động trong iOS 11
Jordan S

246

Lưu ý : Câu trả lời này không hợp lệ cho iOS 11 trở lên.

tôi thích

[mainTableView setContentOffset:CGPointZero animated:YES];

Nếu bạn có một hình nhỏ trên cùng trong chế độ xem bảng của bạn, bạn phải trừ nó:

[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];

12
Cà chua, cà chua. Hmm ... Điều đó không bắt gặp rất rõ ràng bằng văn bản.
FreeAsInBeer

14
Đây là cách tốt nhất để sử dụng khi bạn có chế độ xem đầu trang hoặc chân trang và cũng muốn chúng được bao gồm.
mafonya

6
Đây thực sự là một mã rõ ràng, nhưng nó không hoạt động khi bạn tableViewcó số không contentInsettừ đầu. Ví dụ : tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);. Nếu đó là trường hợp, trong mã của bạn tableViewcuộn đến (0.0f, 5.0f).
tolgamorf

25
Giải pháp cho nhận xét trước đây của tôi:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
tolgamorf

3
Trên iOS 11, bạn nên cân nhắc sử dụng -scrollView.adjustedContentInset.topthay thế.
Marián Černý

79

Hành động có thể:

1

func scrollToFirstRow() {
    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

2

func scrollToLastRow() {
    let indexPath = NSIndexPath(forRow: objects.count - 1, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}

3

func scrollToSelectedRow() {
    let selectedRows = self.tableView.indexPathsForSelectedRows
    if let selectedRow = selectedRows?[0] as? NSIndexPath {
        self.tableView.scrollToRowAtIndexPath(selectedRow, atScrollPosition: .Middle, animated: true)
    }
}

4

func scrollToHeader() {
    self.tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
}

5

func scrollToTop(){
    self.tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
}

Vô hiệu hóa cuộn lên đầu:

func disableScrollsToTopPropertyOnAllSubviewsOf(view: UIView) {
    for subview in view.subviews {
        if let scrollView = subview as? UIScrollView {
            (scrollView as UIScrollView).scrollsToTop = false
        }
        self.disableScrollsToTopPropertyOnAllSubviewsOf(subview as UIView)
    }
}

Sửa đổi và sử dụng nó theo yêu cầu.

Swift 4

  func scrollToFirstRow() {
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
  }

Đó là giải pháp hoàn hảo - scrollToFirstRow
Mehul

Tóm tắt tuyệt vời. Khi bạn có tiêu đề phần, bạn sẽ phải sử dụng tùy chọn4 scrollToHeader.
Vincent

Có cách nào để cuộn lên thanh tìm kiếm phía trên Tableview không?
Tyler Rutt

27

Tốt hơn hết là không sử dụng NSIndexPath (bảng trống), cũng như giả sử rằng điểm cao nhất là CGPointZero (nội dung), đó là những gì tôi sử dụng -

[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];

Hi vọng điêu nay co ich.


Không còn hiệu lực kể từ iOS 11.
rmaddy

21

Swift 4 :

Điều này hoạt động rất tốt:

//self.tableView.reloadData() if you want to use this line remember to put it before 
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)

3
Không phải nếu bạn có một bảngHeadView trong bảng của bạn và nó là nội tuyến (cuộn với nội dung)
finneycanhelp

1
Tôi có cả một đơn giản và một UITableViewStyleGrouped(tiêu đề cuộn với nội dung) và mã này hoạt động. Hãy chắc chắn rằng bạn đang ở trong luồng chính và bạn khởi chạy mã này sau khi khung nhìn xuất hiện ( viewDidAppear). Nếu bạn vẫn gặp sự cố, hãy thử đặt mã bên trong này:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Alessandro Ornano

1
Cảm ơn bạn. Nó sẽ đưa bạn đến ô đầu tiên. Tuy nhiên, nó không hiển thị tiêu đề xem bảng.
finneycanhelp

Điều này sẽ thất bại nếu bảngView trống vì một số lý do (không có ô nào trong phần 0 ở hàng 0)
Maxim Skryabin

17

Tôi đã gặp phải một vấn đề khi gọi thử một số phương thức trống tableView. Đây là một tùy chọn khác cho Swift 4 xử lý các bảng xem trống.

extension UITableView {
  func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
    return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
  }

  func scrollToTop(animated: Bool) {
    let indexPath = IndexPath(row: 0, section: 0)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
      self.scrollToRow(at: indexPath, at: .top, animated: animated)
    }
  }
}

Sử dụng:

// from yourViewController or yourTableViewController
tableView.scrollToTop(animated: true)//or false

Điều này không tài khoản cho bất kỳ tiêu đề bảng hoặc tiêu đề phần.
rmaddy

16

KHÔNG SỬ DỤNG

 tableView.setContentOffset(.zero, animated: true)

Nó đôi khi có thể thiết lập bù không đúng. Ví dụ, trong trường hợp của tôi, tế bào thực sự hơi cao hơn tầm nhìn với các miếng lót trong khu vực an toàn. Không tốt.

CÀI ĐẶT SỬ DỤNG

 tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)

1
Giải pháp hoàn hảo.
Bé Groot

Chính xác những gì tôi đang tìm kiếm, cảm ơn.
Simon

Cả hai giải pháp này đều hợp lệ. Cái đầu tiên không hoạt động trong iOS 11 trở lên. Thứ hai không hoạt động nếu chế độ xem bảng có tiêu đề bảng hoặc phần đầu tiên có tiêu đề phần trừ khi bạn thực sự muốn hàng đầu tiên ở trên cùng và không quan tâm đến việc hiển thị bất kỳ tiêu đề nào.
rmaddy

@rmaddy giải pháp tốt nhất là gì?
ScottyBlades

15

Trên iOS 11, sử dụng adjustedContentInsetđể cuộn chính xác lên trên cùng cho cả hai trường hợp khi thanh trạng thái trong cuộc gọi có hiển thị hay không.

if (@available(iOS 11.0, *)) {
    [tableView setContentOffset:CGPointMake(0, -tableView.adjustedContentInset.top) animated:YES];
} else {
    [tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:YES];
}

Nhanh:

if #available(iOS 11.0, *) {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.adjustedContentInset.top), animated: true)
} else {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
}

12

Đối với các bảng có a contentInset, đặt bù nội dung thành CGPointZerosẽ không hoạt động. Nó sẽ cuộn đến đầu nội dung so với cuộn lên đầu bảng.

Thay vào đó, việc đưa nội dung vào tài khoản sẽ tạo ra điều này:

[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];

1
Cảm ơn bạn, tôi tiếp tục đặt nó thành CGPointZero và không thể hiểu tại sao điều này lại xảy ra.
johnrechd

Không còn hiệu lực kể từ iOS 11.
rmaddy

10

Mã này cho phép bạn cuộn một phần cụ thể lên đầu

CGRect cellRect = [tableinstance rectForSection:section];
CGPoint origin = [tableinstacne convertPoint:cellRect.origin 
                                    fromView:<tableistance>];
[tableinstance setContentOffset:CGPointMake(0, origin.y)];

Đây là mã đơn giản nhất và nó hoạt động tốt. Tôi thực sự đã đưa CGPointMake (0.0f, 0.0f). Chúc mừng!
Felipe

Mã này rất hữu ích để làm cho phần cuộn lên trên cùng
srinivas n

8

Nhanh:

tableView.setContentOffset(CGPointZero, animated: true)

Không còn hiệu lực kể từ iOS 11.
rmaddy

8

Swift 3

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

nếu tableView.setContentOffsetkhông làm việc

Sử dụng:

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()

1
Điều này không hợp lệ cho iOS 11 trở lên.
rmaddy

7

Vì tôi tableViewcó đầy đủ tất cả các loại miếng lót, đây là thứ duy nhất hoạt động tốt:

Swift 3

if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 {
  tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}

Swift 2

if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
  tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}

điều này hữu ích hơn với tôi
Tejzeratul

câu trả lời tuyệt vời, đánh giá cao nó
Jeremy Bader

7

Thêm vào những gì đã được nói, bạn có thể tạo tiện ích mở rộng (Swift) hoặc danh mục (Mục tiêu C) để làm cho việc này dễ dàng hơn trong tương lai:

Nhanh:

extension UITableView {
    func scrollToTop(animated: Bool) {
        setContentOffset(CGPointZero, animated: animated)
    }
}

Bất cứ khi nào bạn muốn cuộn bất kỳ bảng đã xem nào lên trên cùng, bạn có thể gọi mã sau đây:

tableView.scrollToTop(animated: true)

2
Không còn hiệu lực kể từ iOS 11.
rmaddy

6

Tôi thích những điều sau đây, vì nó tính đến một bản in. Nếu không có hình nhỏ, nó vẫn sẽ cuộn lên trên cùng vì hình nhỏ sẽ là 0.

tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)

Không còn hiệu lực kể từ iOS 11.
rmaddy

5

Swift:

nếu bạn không có tiêu đề bảngView:

tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

nếu vậy :

tableView.setContentOffset(CGPointMake(0, -tableViewheader.frame.height   + UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

5

Swift 5, iOS 13

Tôi biết câu hỏi này đã có rất nhiều câu trả lời nhưng từ kinh nghiệm của tôi, chỉ có một phương pháp luôn hoạt động:

tableView.scrollToRow(at: IndexPath(row: someArray.count - 1, section: 0), at: .bottom, animated: true)

Nếu bạn đang làm việc không đồng bộ, các bảng sinh động với bàn phím, v.v., các câu trả lời khác sẽ thường cuộn xuống gần như dưới cùng, không phải là đáy tuyệt đối. Phương pháp này sẽ đưa bạn đến cuối bảng tuyệt đối mỗi lần.


Bạn cũng cần kiểm tra xem có phần nào không
Onur Tuna

4

Đây là những gì tôi sử dụng để hoạt động chính xác trên iOS 11:

extension UIScrollView {
    func scrollToTop(animated: Bool) {
        var offset = contentOffset
        if #available(iOS 11, *) {
            offset.y = -adjustedContentInset.top
        } else {
            offset.y = -contentInset.top
        }
        setContentOffset(offset, animated: animated)
    }
}

4

Trong Swift 5, cảm ơn câu trả lời của @ rất nhiều

extension UITableView{

    func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
        return indexPath.section < numberOfSections && indexPath.row < numberOfRows(inSection: indexPath.section)
    }

    func scrollToTop(_ animated: Bool = false) {
        let indexPath = IndexPath(row: 0, section: 0)
        if hasRowAtIndexPath(indexPath: indexPath) {
            scrollToRow(at: indexPath, at: .top, animated: animated)
        }
    }

}

Sử dụng:

tableView.scrollToTop()

2
1. Điều này cũng hợp lệ trong Swift 4. 2. Điều này không hoạt động nếu có tiêu đề bảng hoặc tiêu đề phần.
rmaddy

3

sử dụng nội dung Offerset không phải là cách đúng đắn. điều này sẽ tốt hơn vì đó là cách tự nhiên của chế độ xem bảng

tableView.scrollToRow(at: NSIndexPath.init(row: 0, section: 0) as IndexPath, at: .top, animated: true)

2
Điều này sẽ không hoạt động nếu có một tiêu đề bảng hoặc tiêu đề phần.
rmaddy

3

Đây là đoạn mã duy nhất làm việc cho tôi

Swift 4:

    tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: true)

PS 70 là chiều cao của ô tiêu đề và bảng xem của tôi


Đây là cách xa để di chuyển lên trên cùng. Thật vô nghĩa khi sử dụng ba dòng riêng biệt chỉ để đặt bù nội dung. Chỉ có dòng cuối cùng là cần thiết nhưng mã hóa một phần bù cụ thể không phải là giải pháp chính xác.
rmaddy

2
func scrollToTop() {
        NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
        [tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

gọi chức năng này bất cứ nơi nào bạn muốn cuộn UITableView lên đầu


2

Swift 4 thông qua tiện ích mở rộng, xử lý chế độ xem bảng trống:

extension UITableView {
    func scrollToTop(animated: Bool) {
        self.setContentOffset(CGPoint.zero, animated: animated);
    }
}

Điều này không hợp lệ kể từ iOS 11.
rmaddy

2

Tôi sử dụng tabBarControll và tôi có một vài phần trong phần xem bảng của mình ở mỗi tab, vì vậy đây là giải pháp tốt nhất cho tôi.

extension UITableView {

    func scrollToTop(){

        for index in 0...numberOfSections - 1 {
            if numberOfSections > 0 && numberOfRows(inSection: index) > 0 {
                scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true)
                break
            }

            if index == numberOfSections - 1 {
                setContentOffset(.zero, animated: true)
                break
            }
        }

    }

}

1

Tôi đã phải thêm bội số -1 *vào tổng của thanh trạng thái và thanh điều hướng, bởi vì nó sẽ tăng chiều cao ra khỏi màn hình,

self.tableView.setContentOffset(CGPointMake(0 , -1 * 
  (self.navigationController!.navigationBar.height +  
  UIApplication.sharedApplication().statusBarFrame.height) ), animated:true)

1

nhanh chóng

hàng của bạn = selectcellRowNumber phần của bạn nếu bạn có = selectNumber nếu bạn chưa đặt là 0

//UITableViewScrollPocation.Middle hoặc dưới cùng hoặc trên cùng

var lastIndex = NSIndexPath(forRow:  selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)

1

Đây là mã để ScrollTableView lên đầu theo lập trình

Nhanh:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)

1

Trong Swift-3:

self.tableView.setContentOffset(CGPoint.zero, animated: true)

0

Nếu bạn muốn di chuyển cuộn hoạt hình trong bảng, hãy sử dụng mã này. Cuộn di chuyển lên trên cùng với hình ảnh động trong 0,5 giây.

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

[_tableContent scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

[UIView commitAnimations];

0

Với Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
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.