我会说得对。
我有一个UIViewController,里面有两个子视图。最上面的一个(从现在开始称之为HeaderView)是一个自定义UIView,底部是UITableView。 我在InterfaceBuilder中设置它们,以便HeaderView从左侧,顶部和右侧有0个边距,另外它有一个固定的高度。 UITableView直接位于下方,各方都有0个边距。
我的目标是实现一种行为,当我开始滚动UITableView的内容时,HeaderView将开始收缩,UITableView会变得更高而不滚动。这应该继续,直到HeaderView达到最小高度。之后,UITableView应该正常开始滚动。向下滚动时,效果应该相反。
我最初使用UIScrollView而不是UITableView开始这个,我已经达到了预期的效果。方法如下:
将UIScrollView连接到插座
@IBOutlet weak var scrollView: UIScrollView!
在控制器的viewDidLoad()
方法中设置UIScrollViewDelegate
self.scrollView.delegate = self
并声明UIViewController符合协议
拦截:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.adjustScrolling(offset: scrollView.contentOffset.y, scrollView: scrollView)
}
在我的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
}
如果我没有忘记任何事情,这应该足以达到预期的效果。让我分解一下:
actualOffset
将self.MaxHeaderScroll
绑定在0和actualOffset
之间,这只是67(我认为,它是动态计算的,但这并不重要)CATransform3DTranslate
自上次调用此函数后没有更改,我就不用担心任何更改了。这避免了一些无用的计算。actualOffset
将其翻译为负self.header.didScrollBy(actualOffset)
。actualOffset
,以便HeaderView可以在内部应用一些视觉更改。但这并不能说明这个问题。actualOffset
数量来对比滚动。这件作品对于我想要达到的正确视觉效果至关重要。如果我没有这样做,scrollView仍会正确调整大小,但内容会立即开始滚动,这是我不想要的。它只应在HeaderView达到最小高度后才开始滚动。scrollView.subviews[0]
以供日后比较正如我所说,这很好。当我从UIScrollView切换到UITableView时出现问题。我认为它可以工作,因为UITableView继承自UIScrollView 唯一不起作用的代码是6号。我真的不知道出了什么问题所以我只列出我发现和/或注意到的所有内容。希望有人能够帮助我。
UITableViewWrapperView
指的是一个包含其中所有内容的视图。当我更改为UITableView时,此子视图似乎是dequeueReusableCell(withIdentifier:for:)
类型,我找不到任何文档,XCode也不会将其识别为有效类。这已经令人沮丧。self.tableView.tableHeaderView
来设置细胞,UITableView认为顶部细胞实际上是不可见的。我无法解决这个问题。actualOffset
设置为{{1}}高度的UIView以对比滚动,但这会产生一种奇怪的效果,即单元格无法正确滚动,并且当UITableView返回到初始状态时位置,顶部会有差距。对此没有任何线索。我知道这里有很多,所以请不要犹豫,询问更多细节。提前谢谢。
答案 0 :(得分:7)
我最近做了类似的事情,所以我是如何实现它的:
创建一个高度约束常量的UIView并将其链接到您的视图/ VC,让UITableview在UIView后面的VC视图全屏限制。
现在将UITableViews contentInset顶部设置为'headerView'的起始高度,在scrollViewDidScroll中调整常量,直到标题的高度达到最小值。
如果您只是运行它,蓝色区域就是您的“标题”,彩色行就是任何单元格。你可以在蓝色区域自动布局你想要的任何东西,它应该自动调整大小和一切