滚动/调整大小UITableView
我会说得很对。滚动/调整大小UITableView
我有一个UIViewController,它有两个子视图。最上面的一个(我们现在称之为HeaderView)是一个自定义的UIView,最底层的是一个UITableView。
我已经在InterfaceBuilder中设置了它们,以便HeaderView从左边,顶部和右边开始有0个边距,并且它还有一个固定的高度。 UITableView直接在下面,各边都有0的余量。
我的目标是实现这样的行为,当我开始滚动UITableView的内容时,HeaderView将开始收缩并且UITableView在没有滚动的情况下变得更高。这应该继续,直到HeaderView达到最小高度。之后,UITableView应该像平常一样开始滚动。当向下滚动效果应该颠倒。
我最初开始使用UIScrollView而不是UITableView来实现期望的结果。下面是如何:
所述的UIScrollView连接到出口
@IBOutlet weak var scrollView: UIScrollView!
设置UIScrollViewDelegate在控制器的
viewDidLoad()
方法self.scrollView.delegate = self
并宣布的UIViewController以符合协议当UIScrollView滚动时截取:
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
结合其0和self.MaxHeaderScroll
之间这仅仅是67(我认为,它是动态的计算,但这个并不重要) - 如果我看到
actualOffset
自从上次调用这个函数以来没有改变,我懒得去适应任何改变。这避免了一些无用的计算。 - 我将滚动应用到标题,只需在y轴上将
CATransform3DTranslate
翻译为负值actualOffset
。 - 我打电话给
self.header.didScrollBy(actualOffset)
,这样HeaderView可以在内部应用一些可视变化。但这并不能解决问题。 - 我调整了scrollView的大小,以便它保持顶部和底部0的边距,现在HeaderView更高了。
- 我翻译下scrollView的内容相同的
actualOffset
数量来对比滚动。这件作品对于我想达到的正确视觉效果至关重要。如果我没有这样做,scrollView仍然会正确调整大小,但内容会立即开始滚动,这是我不想要的。它应该只在HeaderView达到最小高度时开始滚动。 - 我现在在scrollView中设置一个底部插入,这样我就可以一直滚动到最后。如果没有这个,scrollView的最后一部分会被截断,因为scrollView本身会认为它已经达到了它的内容的末尾。
- 最后我存储
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
设置为高度为actualOffset
的UIView以对比滚动,但这给出了一种奇怪的效果,其中单元格不能正确滚动,并且当UITableView返回初始位置时,最佳。对此也没有任何线索。
我知道这里有很多,所以请不要犹豫,询问更多细节。先谢谢你。
我做了这样的事情最近,所以继承人我如何实现它:
做有高度限制不变一个UIView和链接给你的视图/ VC,你的UITableView受限于VC的看法全屏幕背后UIView。
现在将您的UITableViews contentInset设置为您的'headerView'的起始高度,现在在scrollViewDidScroll中调整常量,直到标题的高度达到最小值。
如果你只要运行它,蓝色区域是你的“头”和有色行只是任何细胞。你可以在蓝色区域自动布置任何你想要的东西,它应该自动调整尺寸和一切
嘿,我设法得到它的工作感谢您的例子。太棒了,我欠你一个! –
只要StackOverflow让我,我也会奖励你的赏金:) –
当你实现targetContentOffset,另一个scrollViewDelegate方法时,它也会得到易货贸易,这意味着你可以停止在最小/最大高度之间结束的滚动动画,如果这就是你需要 – SeanLintern88
只是做一个演示 – SeanLintern88
@ SeanLintern88有没有运气? –
嘿,我做了一个演示,但后来重新读你的问题,并不确定我是否覆盖了所有,请看看演示 – SeanLintern88