mkz
mkz

Reputation: 2302

instantly scroll tableView to indexPath

I have to scroll tableView to indexPath immediately after my screen appears. Here is what I've tried but it doesn't work at start. It works only when tableView has loaded and then I press a button which scrolls tableView.

func scrollTableViewToCell() {
    let indexPath = NSIndexPath(forItem: 8, inSection: 1)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Middle, animated: true)
}

I've also tried this but it doesn't work as I need:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    println(indexPath)
    println(NSIndexPath(forRow: tableView.indexPathsForVisibleRows()!.last!.row, inSection: 2))
    if indexPath == NSIndexPath(forRow: tableView.indexPathsForVisibleRows()!.last!.row, inSection: 0) {
        scrollTableViewToCell()
    }
}

I've also tried this)

override func viewDidLayoutSubviews() {
    self.view.layoutIfNeeded()
    scrollTableViewToCell()
}

Can someone tell me how to know when tableView has loaded all cells and then scroll it to NSIndexPath(forItem: 8, inSection: 1) ?

UPDATE::

Here is how I load the data to tableView:

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return years.count
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return allInfo[years[section]]!.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("tutionTableViewCell") as! TuitionTableViewCell
    cell.selectionStyle = .None

    let info = allInfo[years[indexPath.section]]! as [String: String?]

    cell.monthLabel.text = months[indexPath.row]
    if info[months[indexPath.row]]! != nil {
        cell.tuitionLabel.hidden = false
        cell.tuitionLabel.text = info[months[indexPath.row]]!
    } else {
        cell.tuitionLabel.hidden = true
    }
    if info[months[indexPath.row]]! == "Nog te betalen" {
        cell.monthLabel.textColor = UIColor(hex: 0xff0000).colorWithAlphaComponent(0.87)
        cell.tuitionLabel.textColor = UIColor(hex: 0xff0000).colorWithAlphaComponent(0.87)
    } else {
        cell.monthLabel.textColor = UIColor.blackColor().colorWithAlphaComponent(0.87)
        cell.tuitionLabel.textColor = UIColor.blackColor().colorWithAlphaComponent(0.87)
    }
    return cell
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return years[section]
}

func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
    header.textLabel.font = UIFont(name: "Roboto-Regular", size: 16)
    header.textLabel.text = self.tableView(self.tableView, titleForHeaderInSection: section)
    let headerFrame = header.frame
    header.textLabel.frame = headerFrame
    header.textLabel.textColor = UIColor.blackColor().colorWithAlphaComponent(0.54)
    header.textLabel.backgroundColor = UIColor(hex: 0xf9f9f9)
    header.contentView.backgroundColor = UIColor(hex: 0xf9f9f9)
}

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 35
}

SECOND UPDATE::

My hardcoded data:

var years: [String] = ["2015", "2016", "2017"]
var months: [String] = ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"]
var allInfo: [String: [String: String?]] = [String: [String: String?]]()

override func viewDidLoad() {
    self.tableView.separatorStyle = .None
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = 150.0

    allInfo[years[0]] = ["Januari": "300,00", "Februari": "300,00", "Maart": "300,00", "April": "300,00", "Mei": "300,00", "Juni": "300,00", "Juli": "300,00", "Augustus": "300,00", "September": "300,00", "Oktober": "300,00", "November": "300,00", "December": "300,00"]
    allInfo[years[1]] = ["Januari": "300,00", "Februari": "300,00", "Maart": "300,00", "April": "300,00", "Mei": "300,00", "Juni": "300,00", "Juli": "300,00", "Augustus": "300,00", "September": "Nog te betalen", "Oktober": nil, "November": nil, "December": nil]
    allInfo[years[2]] = ["Januari": nil, "Februari": nil, "Maart": nil, "April": nil, "Mei": nil, "Juni": nil, "Juli": nil, "Augustus": nil, "September": nil, "Oktober": nil, "November": nil, "December": nil]

    tableView.reloadData()
    scrollTableViewToCell()
}

Upvotes: 2

Views: 3348

Answers (3)

user8716887
user8716887

Reputation:

Set a timer in viewdidload. This will solve your problem.

    Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.scrollToRowMethod), userInfo: nil, repeats: false)

Upvotes: 1

mkz
mkz

Reputation: 2302

Thanks a lot to @Paulw11 for helping me with my problem.

I solved it by removing these two lines of code in viewDidLoad:

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 150.0

Now it scrolls as needed!

Also, scrolling lag was removed by adding scrolling animation:

self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Middle, animated: true)

Upvotes: 0

Paulw11
Paulw11

Reputation: 114818

Make sure you have implemented the method estimatedHeightForRowAtIndexPath -

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 44
}

As you are scrolling the tableview directly to a row that is below cells that have never been rendered the tableview can't correctly lay out the cells if it doesn't know the size of the 'missing' cells.

Implementing this method in my test app resolved the scroll issue and the strange "flicking" I was seeing when I scrolled up.

Also, you should call super.viewDidLoad() in your viewDidLoad method

Upvotes: 0

Related Questions