滚动/调整 UITableView
Posted
技术标签:
【中文标题】滚动/调整 UITableView【英文标题】:scrolling/resizing UITableView 【发布时间】:2017-05-09 08:15:01 【问题描述】:我会直入主题。
我有一个 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 符合协议
在 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 的大小,现在 HeaderView 更高了,因此它从顶部和底部保持 0 边距。
我将滚动视图的内容向下平移相同的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 被带回初始位置时,会有成为顶部的差距。对此也没有任何线索。
我知道这里有很多,所以请不要犹豫,询问更多详细信息。提前谢谢你。
【问题讨论】:
只是做一个演示 @SeanLintern88 运气好吗? 嘿,我做了一个演示,但后来重新阅读了你的问题,不确定我是否涵盖了所有内容,请看演示 运气好吗?如果您有任何问题,我会在接下来的一个小时内:D 【参考方案1】:我最近做了这样的事情,所以这是我实现它的方法:
制作一个具有高度约束常量的 UIView 并将其链接到您的视图/VC,您是否将 UITableview 约束到 UIView 后面的 VC 视图全屏。
现在将 UITableViews contentInset top 设置为“headerView”的起始高度,在 scrollViewDidScroll 中调整常量,直到标题的高度达到最小值。
Here is a demo
如果您只是运行它,蓝色区域是您的“标题”,而彩色行是任何单元格。你可以在蓝色区域自动布局任何你想要的东西,它应该自动调整大小和一切
【讨论】:
嘿伙计,多亏了你的例子,我设法让它工作了。太棒了,我欠你一个! 只要 *** 允许我,我也会奖励你赏金 :) 当你实现 targetContentOffset 时,它也会变得易货,这是另一个 scrollViewDelegate 方法,这意味着如果你需要的话,你可以停止在最小/最大高度之间结束的滚动动画 当我禁用弹跳属性并从默认状态向下滚动(在视觉上什么都不做)时,我遇到了一个问题,向上滚动而不抬起手指什么都不会发生,直到我到达y
点 i开始往下拖。为什么会这样?我们如何才能克服它以允许更快速的砍伐。找不到解决方案@SeanLintern以上是关于滚动/调整 UITableView的主要内容,如果未能解决你的问题,请参考以下文章