滚动/调整UITableView的大小

Fra*_*.M. 1 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滚动时的拦截:
    func scrollViewDidScroll(_ scrollView: UIScrollView) { self.adjustScrolling(offset: scrollView.contentOffset.y, scrollView: scrollView) }

  4. 在我的adjustScrolling(offset:scrollView:)方法中,"神奇"发生了

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

    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
    }
Run Code Online (Sandbox Code Playgroud)

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

  1. 我计算actualOffset它在0和self.MaxHeaderScroll只有67 之间的绑定(我想,它是动态计算的,但这并不重要)
  2. 如果我发现actualOffset自上次调用此函数以来没有改变,我不打算任何改变.这避免了一些无用的计算.
  3. 我将滚动应用于标题,将其翻译CATransform3DTranslate为y轴上的负数actualOffset.
  4. 我打电话self.header.didScrollBy(actualOffset)让HeaderView可以在内部应用一些视觉变化.但这并不能说明这个问题.
  5. 我调整了scrollView的大小,以便在HeaderView更高的情况下从顶部和底部保留0个边距.
  6. 我将scrollView的内容翻译成相同的actualOffset量来对比滚动.这件作品对于我想要达到的正确视觉效果至关重要.如果我没有这样做,scrollView仍然会正确调整大小,但内容会立即开始滚动,这是我不想要的.一旦HeaderView达到最小高度,它应该只开始滚动.
  7. 我现在在scrollView中设置了一个底部插图,这样我就可以一直滚动到最后.如果没有这个,scrollView的最后一部分将被切断,因为scrollView本身会认为它到达了它的内容的末尾.
  8. 最后我存储了actualOffset以供以后比较

正如我所说,这很好.当我从UIScrollView切换到UITableView时出现问题.我认为它可以工作,因为UITableView继承自UIScrollView.
唯一不起作用的代码是6号.我真的不知道出了什么问题所以我只列出我发现和/或注意到的所有内容.希望有人能够帮助我.

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

我知道这里有很多,所以请不要犹豫,询问更多细节.先感谢您.

Sea*_*ern 7

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

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

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

这是一个演示

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