滚动/调整大小UITableView

时间:2017-05-09 08:15:01

标签: ios swift swift3

我会说得对。

我有一个UIViewController,里面有两个子视图。最上面的一个(从现在开始称之为HeaderView)是一个自定义UIView,底部是UITableView。 我在InterfaceBuilder中设置它们,以便HeaderView从左侧,顶部和右侧有0个边距,另外它有一个固定的高度。 UITableView直接位于下方,各方都有0个边距。

我的目标是实现一种行为,当我开始滚动UITableView的内容时,HeaderView将开始收缩,UITableView会变得更高而不滚动。这应该继续,直到HeaderView达到最小高度。之后,UITableView应该正常开始滚动。向下滚动时,效果应该相反。

我最初使用UIScrollView而不是UITableView开始这个,我已经达到了预期的效果。方法如下:

  1. 将UIScrollView连接到插座
    @IBOutlet weak var scrollView: UIScrollView!

  2. 在控制器的viewDidLoad()方法中设置UIScrollViewDelegate self.scrollView.delegate = self 并声明UIViewController符合协议

  3. 当UIScrollView滚动时,
  4. 拦截:
    func scrollViewDidScroll(_ scrollView: UIScrollView) { self.adjustScrolling(offset: scrollView.contentOffset.y, scrollView: scrollView) }

  5. 在我的adjustScrolling(offset:scrollView:)方法中"魔法"发生

  6. 现在让我们来看看这种方法会发生什么。

        private func adjustScrolling(offset: CGFloat, scrollView: UIScrollView) {
    
            // bind value between 0 and max header scroll
            let actualOffset: CGFloat = offset < 0 ? 0 : (offset >= self.maxHeaderScroll ? self.maxHeaderScroll : offset)
    
            // avoid useless calculations
            if (actualOffset == self.currentOffset) {
                return
            }
    
            /**
             * Apply the vertical scrolling to the header
             */
            // Translate the header up to give more space to the scrollView
            let headerTransform = CATransform3DTranslate(CATransform3DIdentity, 0, -(actualOffset), 0)
            self.header.layer.transform = headerTransform
            // Adjust header's subviews to new size
            self.header.didScrollBy(actualOffset)
    
            /**
             * Apply the corrected vertical scrolling to the scrollView
             */
            // Resize the scrollView to fill all empty space
            let newScrollViewY = self.header.frame.origin.y + self.header.frame.height
            scrollView.frame = CGRect(
                x: 0,
                y: newScrollViewY,
                width: scrollView.frame.width,
                height: scrollView.frame.height + (scrollView.frame.origin.y - newScrollViewY)
            )
            // Translate the scrollView's content view down to contrast scrolling
            let scrollTransform = CATransform3DTranslate(CATransform3DIdentity, 0, (actualOffset), 0)
            scrollView.subviews[0].layer.transform = scrollTransform
            // Set bottom inset to show content hidden by translation
            scrollView.contentInset = UIEdgeInsets(
                top: 0,
                left: 0,
                bottom: actualOffset,
                right: 0
            )
    
            self.currentOffset = actualOffset
        }
    

    如果我没有忘记任何事情,这应该足以达到预期的效果。让我分解一下:

    1. 我计算actualOffsetself.MaxHeaderScroll绑定在0和actualOffset之间,这只是67(我认为,它是动态计算的,但这并不重要)
    2. 如果我发现CATransform3DTranslate自上次调用此函数后没有更改,我就不用担心任何更改了。这避免了一些无用的计算。
    3. 我将滚动应用于标题,方法是在y轴上用actualOffset将其翻译为负self.header.didScrollBy(actualOffset)
    4. 我调用actualOffset,以便HeaderView可以在内部应用一些视觉更改。但这并不能说明这个问题。
    5. 我调整了scrollView的大小,以便在HeaderView更高的情况下从顶部和底部保留0个边距。
    6. 我将scrollView的内容翻译成相同的actualOffset数量来对比滚动。这件作品对于我想要达到的正确视觉效果至关重要。如果我没有这样做,scrollView仍会正确调整大小,但内容会立即开始滚动,这是我不想要的。它只应在HeaderView达到最小高度后才开始滚动。
    7. 我现在在scrollView中设置了一个底部插图,这样我就可以一直滚动到最后。如果没有这个,scrollView的最后一部分将会被切断,因为scrollView本身会认为它已经达到了它的内容。
    8. 最后,我存储scrollView.subviews[0]以供日后比较
    9. 正如我所说,这很好。当我从UIScrollView切换到UITableView时出现问题。我认为它可以工作,因为UITableView继承自UIScrollView 唯一不起作用的代码是6号。我真的不知道出了什么问题所以我只列出我发现和/或注意到的所有内容。希望有人能够帮助我。

      • 对于UIScrollView,在第6点中,UITableViewWrapperView指的是一个包含其中所有内容的视图。当我更改为UITableView时,此子视图似乎是dequeueReusableCell(withIdentifier:for:)类型,我找不到任何文档,XCode也不会将其识别为有效类。这已经令人沮丧。
      • 如果在第6点我也在x轴上给出了一些翻译(让我们说50)我可以看到一个初始非常快速的翻译,它会立即恢复为0.这只会在UITableView开始滚动时发生,滚动时不会继续。
      • 我尝试在第6点更改子视图的帧以获得所需的结果。虽然滚动是正确的,但在滚动UITableView时,顶部单元格开始消失。我瘦这是因为我使用self.tableView.tableHeaderView来设置细胞,UITableView认为顶部细胞实际上是不可见的。我无法解决这个问题。
      • 我尝试将actualOffset设置为{{1}}高度的UIView以对比滚动,但这会产生一种奇怪的效果,即单元格无法正确滚动,并且当UITableView返回到初始状态时位置,顶部会有差距。对此没有任何线索。

      我知道这里有很多,所以请不要犹豫,询问更多细节。提前谢谢。

1 个答案:

答案 0 :(得分:7)

我最近做了类似的事情,所以我是如何实现它的:

创建一个高度约束常量的UIView并将其链接到您的视图/ VC,让UITableview在UIView后面的VC视图全屏限制。

现在将UITableViews contentInset顶部设置为'headerView'的起始高度,在scrollViewDidScroll中调整常量,直到标题的高度达到最小值。

Here is a demo

如果您只是运行它,蓝色区域就是您的“标题”,彩色行就是任何单元格。你可以在蓝色区域自动布局你想要的任何东西,它应该自动调整大小和一切