Swift中带有标题的TableView的自定义分页大小(一次滚动一个单元格)

Posted

技术标签:

【中文标题】Swift中带有标题的TableView的自定义分页大小(一次滚动一个单元格)【英文标题】:Custom Paging Size for TableView with Header in Swift (Scroll One Cell At a Time) 【发布时间】:2015-07-20 02:29:49 【问题描述】:

我有一个包含多个部分的 UITableView,每个部分都有一个标题。表格的大小使得一个标题和一个单元格占据表格的整个框架。我想允许用户一次只滚动一个单元格。当我设置 paging = enabled 时,滚动无法按预期工作,因为表格一次滚动一个整个表格框架,而不是一次滚动一个单元格。这会导致不希望的偏移量在您滚动表格时不断变大。

到目前为止,我的研究表明我需要重写 scrollViewWillBeginDragging。参见例如UITableView with custom paging-like behaviour。但是我读到的关于这个主题的每一篇文章都一定是在 Swift 之前出现的,因为它们都是用 Objective C 编写的。

请建议 Swift 代码来完成带有节标题的表格视图的单个单元格分页。尽管可能需要禁用分页本身,但解决方案应尽可能接近真正的分页。

下面是我的表格大小的代码。表格的框架大小为 475。

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    if (condition == true) 
        return CGFloat(425)
    
    else 
        return CGFloat(375)
    


func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat 

    if (condition == true) 
        return CGFloat(47)
    
    else 
        return CGFloat(90)
    

更新:这里的最佳答案 (Force UITableView to Scroll to Tops of Cells) 似乎也很相关。但是,同样,这一切都在 Objective C 中。如果这些链接中的任何一个答案被证明是正确的,那么将该答案简单地翻译成 Swift 就足够了。

更新 2 我几乎想通了。但是边缘情况不起作用(即,在表格的最顶部和最底部)。也就是说,我得到了一个类似分页的滚动动作,除非我尝试向下滚动到表格中的最后一个单元格。没有捕捉到最后一个单元格。它只是像往常一样滚动。我怀疑它与最后一个单元格的 frame.origin.y 有关。

请帮我弄清楚这些边缘情况。代码如下:

viewDidLoad() 
      self.tableView.decelerationRate = UIScrollViewDecelerationRateFast


var lastContentOffset:CGPoint!
var initialIndexPath:NSIndexPath?
func scrollViewWillBeginDragging(scrollView: UIScrollView) 
    lastContentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y)
    var visibleCellIndexes = tableView.indexPathsForVisibleRows() as! [NSIndexPath]
    initialIndexPath = visibleCellIndexes[0]




var scrolledToPath:NSIndexPath?
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) 
    if (scrollView == self.tableView) 


        var lastIndexPath:NSIndexPath!
        var nextIndexPath:NSIndexPath!
        if let p = scrolledToPath 
            lastIndexPath = scrolledToPath
        
        else if let u = initialIndexPath 
            lastIndexPath = initialIndexPath
        
        if (lastContentOffset.y <= scrollView.contentOffset.y) 
            // scrolling down
            if (lastIndexPath.row == numRows(lastIndexPath.section)-1) 
                // last row in section
                if (lastIndexPath.section == numSections(self.tableView)-1) 
                    // last  section
                    nextIndexPath = lastIndexPath
                
                else 
                    nextIndexPath = NSIndexPath(forRow: 0, inSection: lastIndexPath.section+1)
                
            
            else 
                nextIndexPath = NSIndexPath(forRow: lastIndexPath.row+1, inSection: lastIndexPath.section)
            
        
        else if (lastContentOffset.y > scrollView.contentOffset.y) 
            // scrolling up
            if (lastIndexPath.row == 0) 
                // first row in section
                if (lastIndexPath.section == 0) 
                    // first section
                    nextIndexPath = lastIndexPath
                
                else 
                    nextIndexPath = NSIndexPath(forRow: numRows(lastIndexPath.section-1)-1, inSection: lastIndexPath.section-1)
                
            
            else 
                nextIndexPath = NSIndexPath(forRow: lastIndexPath.row-1, inSection: lastIndexPath.section)
            

        

        scrolledToPath = nextIndexPath

        var headerHeight = CGFloat(47)
        if (condition == true) 
            headerHeight = CGFloat(90)
        

        var rectOfNextIndexPath:CGRect = self.tableView.rectForRowAtIndexPath(nextIndexPath)
        targetContentOffset.memory.y = rectOfNextIndexPath.origin.y - headerHeight

    

【问题讨论】:

UITableView Pagination 的可能副本 这个问题早在 2012 年 Swift 之前。请用 Swift 提供答案。 【参考方案1】:

已修复。在我的 tableview 中调整大小会弄乱最终情况。在我确保单元格大小正确后,它工作得很好。下面是swift中tableview类页面滚动的解决方案。

viewDidLoad() 
      self.tableView.decelerationRate = UIScrollViewDecelerationRateFast


var lastContentOffset:CGPoint!
var initialIndexPath:NSIndexPath?
func scrollViewWillBeginDragging(scrollView: UIScrollView) 
    lastContentOffset = CGPointMake(scrollView.contentOffset.x,     scrollView.contentOffset.y)
    var visibleCellIndexes = tableView.indexPathsForVisibleRows() as! [NSIndexPath]
    initialIndexPath = visibleCellIndexes[0]




var scrolledToPath:NSIndexPath?
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) 

    var lastIndexPath:NSIndexPath!
    var nextIndexPath:NSIndexPath!
    if let p = scrolledToPath 
        lastIndexPath = scrolledToPath
    
    else if let u = initialIndexPath 
        lastIndexPath = initialIndexPath
    
    if (lastContentOffset.y <= scrollView.contentOffset.y) 
        // scrolling down
        if (lastIndexPath.row == numRows(lastIndexPath.section)-1) 
            // last row in section
            if (lastIndexPath.section == numSections(self.tableView)-1) 
                // last  section
                nextIndexPath = lastIndexPath
            
            else 
                nextIndexPath = NSIndexPath(forRow: 0, inSection: lastIndexPath.section+1)
            
        
        else 
            nextIndexPath = NSIndexPath(forRow: lastIndexPath.row+1, inSection: lastIndexPath.section)
        
    
    else if (lastContentOffset.y > scrollView.contentOffset.y) 
        // scrolling up
        if (lastIndexPath.row == 0) 
            // first row in section
            if (lastIndexPath.section == 0) 
                // first section
                nextIndexPath = lastIndexPath
            
            else 
                nextIndexPath = NSIndexPath(forRow: numRows(lastIndexPath.section-1)-1, inSection: lastIndexPath.section-1)
            
        
        else 
            nextIndexPath = NSIndexPath(forRow: lastIndexPath.row-1, inSection: lastIndexPath.section)
        

    

    scrolledToPath = nextIndexPath

    var headerHeight = CGFloat(47)
    if (condition == true) 
        headerHeight = CGFloat(90)
    

    var rectOfNextIndexPath:CGRect = self.tableView.rectForRowAtIndexPath(nextIndexPath)
    targetContentOffset.memory.y = rectOfNextIndexPath.origin.y - headerHeight



【讨论】:

以上是关于Swift中带有标题的TableView的自定义分页大小(一次滚动一个单元格)的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中带有 CollectionView 和 TableView 的 UIView

Swift 4.2 中带有 JSON 数据的 Tableview

表格内容在使用子视图的自定义单元格的 TableView 滚动上消失 - Swift

Swift 中带有自定义 TableViewCell 的核心数据图像

如何在swift ios中的自定义TableView单元格中显示多个字符串值到多个标签?

如何在一个 tableView 中使用两个不同的自定义单元格?使用情节提要,iOS 7