UITableView - เลื่อนไปด้านบน


393

ในมุมมองตารางของฉันฉันต้องเลื่อนไปด้านบน แต่ฉันไม่สามารถรับประกันได้ว่าวัตถุแรกจะเป็นส่วนที่ 0 แถวที่ 0 อาจเป็นไปได้ว่ามุมมองตารางของฉันจะเริ่มจากส่วนหมายเลข 5

ดังนั้นฉันจะได้รับข้อยกเว้นเมื่อฉันโทร:

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

มีวิธีอื่นในการเลื่อนไปที่ด้านบนของมุมมองตารางหรือไม่

คำตอบ:


857

UITableView เป็น subclass ของ UIScrollView ดังนั้นคุณสามารถใช้:

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

หรือ

[mainTableView setContentOffset:CGPointZero animated:YES];

และใน Swift:

mainTableView.setContentOffset(CGPointZero, animated:true)

และใน Swift 3 & สูงกว่า:

mainTableView.setContentOffset(.zero, animated: true)

9
ฉันแรกลองนี้กับ CGRectZero ซึ่งเทียบเท่ากับ CGRectMake (0, 0, 0, 0) สิ่งนี้ไม่ทำงาน แต่สิ่งที่กล่าวมาข้างต้นนั้นแปลก ฉันเดาว่ามันต้องมีความกว้างและความสูงเป็นบวก ขอบคุณ.
Keller

5
หมายเหตุคุณจะต้องการภาพเคลื่อนไหว: NOหากคุณเรียกใช้ใน scrollToRowAtIndexPath: เพื่อให้ตารางเริ่มต้นในตำแหน่งที่ถูกต้อง หวังว่ามันจะช่วย!
Fattie

3
@ hasan83 CGRectMake (0, 0, 0, 0) หรือ CGRectZero ไม่ใช่ rect ที่มองเห็นได้ ฉันจะบอกว่า [mainTableView setContentOffset: CGPointZero animated: YES]; คือการแสดงออกที่สวยกว่า
catlan

8
มีใครสังเกตเห็นว่าใน iOS11 ทั้งหมดนี้ใช้งานไม่ได้และเลื่อนไม่ถูกต้องในบางกรณี?
Peter Lapisu

11
@PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)ดูเหมือนว่าจะทำงานใน iOS 11
Jordan S

246

หมายเหตุ : คำตอบนี้ไม่ถูกต้องสำหรับ iOS 11 และใหม่กว่า

ฉันชอบ

[mainTableView setContentOffset:CGPointZero animated:YES];

หากคุณมีสิ่งที่ใส่เข้าไปด้านบนในมุมมองตารางของคุณคุณต้องลบมัน:

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

12
มะเขือเทศมะเขือเทศ อืม ... มันไม่ได้เขียนไว้อย่างชัดเจนนัก
FreeAsInBeer เมื่อ

14
นี่เป็นวิธีที่ดีที่สุดที่จะใช้เมื่อคุณมีมุมมองส่วนหัวของตารางหรือส่วนท้ายและต้องการให้รวมไว้ด้วย
mafonya

6
นี่เป็นรหัสที่ชัดเจน แต่ใช้ไม่ได้เมื่อคุณtableViewมีค่าไม่เป็นศูนย์contentInsetจากด้านบน ตัวอย่างเช่นtableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);. หากเป็นกรณีที่ในรหัสของคุณเลื่อนไปtableView (0.0f, 5.0f)
tolgamorf

25
วิธีการแก้ไขความคิดเห็นก่อนหน้าของฉัน:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
tolgamorf

3
บน iOS 11 คุณควรพิจารณาใช้-scrollView.adjustedContentInset.topแทน
MariánČerný

79

การกระทำที่เป็นไปได้:

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

ปิดการใช้งาน Scroll To Top:

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

ดัดแปลงและใช้งานได้ตามความต้องการ

สวิฟต์ 4

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

นั่นเป็นวิธีการแก้ปัญหาที่สมบูรณ์แบบ - scrollToFirstRow
Mehul

สรุปยอดเยี่ยม เมื่อคุณมีส่วนหัวคุณจะต้องใช้ option4 scrollToHeader
Vincent

มีวิธีเลื่อนไปยังแถบค้นหาที่อยู่เหนือ Tableview หรือไม่
Tyler Rutt

27

จะดีกว่าถ้าไม่ใช้ NSIndexPath (ตารางว่าง) และไม่คิดว่าจุดบนสุดคือ CGPointZero (เนื้อหาแทรก) นั่นคือสิ่งที่ฉันใช้ -

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

หวังว่านี่จะช่วยได้


ไม่สามารถใช้งานได้อีกต่อไปใน iOS 11
rmaddy

21

สวิฟท์ 4 :

วิธีนี้ใช้งานได้ดีมาก:

//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
ไม่ใช่ถ้าคุณมี tableHeaderView ใน tableView ของคุณและมันเป็นแบบอินไลน์ (เลื่อนไปตามเนื้อหา)
finneycanhelp

1
ฉันมีทั้งธรรมดาและ a UITableViewStyleGrouped(ส่วนหัวเลื่อนด้วยเนื้อหา) และรหัสนี้ทำงาน ต้องแน่ใจว่าคุณอยู่ในเธรดหลักและคุณเปิดใช้รหัสนี้หลังจากที่มุมมองปรากฏขึ้น ( viewDidAppear) หากคุณยังคงมีปัญหาลองใส่รหัสไว้ในนี้:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Alessandro Ornano

1
ขอบคุณ. มันจะพาคุณไปยังเซลล์แรก อย่างไรก็ตามจะไม่แสดงส่วนหัวของมุมมองตาราง
finneycanhelp

สิ่งนี้จะล้มเหลวหาก tableView ว่างเปล่าด้วยเหตุผลบางอย่าง (ไม่มีเซลล์ในส่วน 0 ที่ 0 แถว)
Maxim Skryabin

17

tableViewฉันได้พบปัญหาโทรพยายามบางส่วนของวิธีการในที่ว่างเปล่า นี่คืออีกตัวเลือกสำหรับ Swift 4 ที่จัดการการดูตารางที่ว่างเปล่า

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

การใช้งาน:

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

นี่ไม่ได้คำนึงถึงส่วนหัวของตารางหรือส่วนหัวของส่วนใด ๆ
rmaddy

16

ไม่ใช้

 tableView.setContentOffset(.zero, animated: true)

บางครั้งสามารถตั้งค่าออฟเซตได้อย่างไม่ถูกต้อง ตัวอย่างเช่นในกรณีของฉันเซลล์จริง ๆ แล้วอยู่เหนือมุมมองเล็กน้อยโดยมีส่วนที่ปลอดภัยอยู่ ไม่ดี.

ใช้แทน

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

1
โซลูชั่นที่สมบูรณ์แบบ
Baby Groot

ขอบคุณสิ่งที่ฉันกำลังมองหาขอบคุณ
Simon

วิธีแก้ปัญหาเหล่านี้ไม่ถูกต้อง ตัวแรกไม่ทำงานภายใต้ iOS 11 หรือใหม่กว่า ที่สองไม่ทำงานหากมุมมองตารางมีส่วนหัวของตารางหรือส่วนแรกมีส่วนหัวของส่วนเว้นแต่คุณต้องการแถวแรกที่ด้านบนและไม่สนใจแสดงส่วนหัวใด ๆ
rmaddy

@rmaddy ทางออกที่ดีที่สุดคืออะไร?
ScottyBlades

15

บน iOS 11 ใช้adjustedContentInsetเพื่อเลื่อนไปด้านบนอย่างถูกต้องสำหรับทั้งสองกรณีเมื่อแถบสถานะระหว่างการโทรมองเห็นได้หรือไม่

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

สวิฟท์:

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

สำหรับตารางที่มีการcontentInsetตั้งค่าเนื้อหาจะชดเชยCGPointZeroจะไม่ทำงาน มันจะเลื่อนไปที่เนื้อหาด้านบนเทียบกับการเลื่อนไปที่ด้านบนของตาราง

การนำเนื้อหาที่ใส่เข้าไปในบัญชีมาสร้างสิ่งนี้แทน:

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

1
ขอบคุณฉันตั้งค่าไว้ที่ CGPointZero และไม่เข้าใจว่าทำไมสิ่งนี้จึงเกิดขึ้น
johnrechd

ไม่สามารถใช้งานได้อีกต่อไปใน iOS 11
rmaddy

10

รหัสนี้ให้คุณเลื่อนหัวข้อเฉพาะไปด้านบน

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

นี่เป็นรหัสที่ง่ายที่สุดและใช้งานได้ดี ฉันใส่ CGPointMake จริง ๆ (0.0f, 0.0f) ไชโย!
เฟลิเป้

รหัสนี้มีประโยชน์มากในการทำให้ส่วนเลื่อนด้านบน
srinivas n


8

สวิฟท์ 3

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

ถ้า tableView.setContentOffsetไม่ทำงาน

ใช้:

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

1
สิ่งนี้ไม่ถูกต้องสำหรับ iOS 11 หรือใหม่กว่า
rmaddy

7

ตั้งแต่ฉัน tableViewเต็มไปด้วยสิ่งที่ใส่เข้าไปทุกชนิดนี่เป็นสิ่งเดียวที่ทำงานได้ดี:

สวิฟท์ 3

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

สวิฟท์ 2

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

สิ่งนี้มีประโยชน์มากสำหรับฉัน
Tejzeratul

คำตอบที่ดีขอบคุณมัน
Jeremy Bader

7

เมื่อเพิ่มสิ่งที่กล่าวไปแล้วคุณสามารถสร้างส่วนขยาย (Swift) หรือหมวดหมู่ (Objective C) เพื่อทำให้สิ่งนี้ง่ายขึ้นในอนาคต:

สวิฟท์:

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

ทุกครั้งที่คุณต้องการเลื่อน tableView ที่กำหนดไว้ไปด้านบนคุณสามารถเรียกรหัสต่อไปนี้:

tableView.scrollToTop(animated: true)

2
ไม่สามารถใช้งานได้อีกต่อไปใน iOS 11
rmaddy

6

ฉันชอบสิ่งต่อไปนี้เนื่องจากคำนึงถึงสิ่งที่ใส่เข้าไป หากไม่มีสิ่งที่ใส่เข้าไปมันจะยังคงเลื่อนไปด้านบนเนื่องจากส่วนแทรกจะเป็น 0

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

ไม่สามารถใช้งานได้ตั้งแต่ iOS 11
rmaddy

5

รวดเร็ว:

หากคุณไม่มีส่วนหัวของ tableView:

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

ถ้าเป็นเช่นนั้น:

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

5

Swift 5, iOS 13

ฉันรู้ว่าคำถามนี้มีคำตอบมากมาย แต่จากประสบการณ์ของฉันมีเพียงวิธีเดียวที่ใช้งานได้:

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

หากคุณทำงานในแบบ async ตารางที่เคลื่อนไหวด้วยคีย์บอร์ด ฯลฯ คำตอบอื่น ๆ มักจะเลื่อนไปที่ด้านล่างเกือบไม่ใช่ด้านล่างแบบสัมบูรณ์ วิธีนี้จะพาคุณไปยังจุดสิ้นสุดของตารางทุกครั้ง


คุณต้องตรวจสอบว่ามีส่วนหรือไม่
Onur Tuna

4

นี่คือสิ่งที่ฉันใช้เพื่อทำงานอย่างถูกต้องบน 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

ใน Swift 5 ขอบคุณ @Adrian ตอบมาก

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

}

การใช้งาน:

tableView.scrollToTop()

2
1. สิ่งนี้ยังใช้ได้ใน Swift 4. 2. มันจะไม่ทำงานถ้ามันมีส่วนหัวของตารางหรือส่วนหัวของส่วน
rmaddy

3

การใช้ contentOffset ไม่ใช่วิธีที่ถูกต้อง สิ่งนี้จะดีกว่าเนื่องจากเป็นวิธีธรรมชาติของมุมมองตาราง

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

2
สิ่งนี้จะไม่ทำงานหากมีส่วนหัวของตารางหรือส่วนหัวของส่วน
rmaddy

3

นี่เป็นข้อมูลโค้ดเดียวที่ทำงานให้ฉัน

สวิฟท์ 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 คือความสูงของเซลล์ส่วนหัวและมุมมองตารางของฉัน


อยู่ไกลจากวิธีที่ถูกต้องเพื่อเลื่อนไปด้านบน ไม่มีเหตุผลที่จะใช้สามบรรทัดแยกกันเพื่อตั้งค่าการชดเชยเนื้อหา ต้องการบรรทัดสุดท้ายเท่านั้น แต่การเข้ารหัสออฟเซ็ตเฉพาะไม่ใช่การแก้ไขที่ถูกต้อง
rmaddy

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

เรียกใช้ฟังก์ชันนี้ทุกที่ที่คุณต้องการเลื่อนดู UITableView ขึ้นไปด้านบน


2

Swift 4ผ่านทางส่วนขยายจัดการกับมุมมองตารางที่ว่างเปล่า:

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

สิ่งนี้ไม่ถูกต้องตั้งแต่ iOS 11
rmaddy

2

ฉันใช้ tabBarController และฉันมีบางส่วนใน tableview ของฉันที่ทุกแท็บดังนั้นนี่เป็นทางออกที่ดีที่สุดสำหรับฉัน

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

ฉันต้องเพิ่มการคูณด้วย-1 *ผลรวมของแถบสถานะและแถบการนำทางเพราะมันจะสูงจากหน้าจอ

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

1

อย่างรวดเร็ว

your row = selectioncellRowNumber ส่วนของคุณหากคุณมี = selectionNumber หากคุณไม่ได้ตั้งค่าไว้ที่ศูนย์

//UITableViewScrollPosition.Middle หรือ Bottom หรือ Top

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

1

นี่คือรหัสสำหรับ ScrollTable ดูไปด้านบนโดยทางโปรแกรม

สวิฟท์:

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


0

หากคุณต้องการย้ายภาพเคลื่อนไหวการเลื่อนในตารางให้ใช้รหัสนี้ เลื่อนไปด้านบนด้วยภาพเคลื่อนไหวใน. 5 วินาที

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

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

[UIView commitAnimations];

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.