在无限的 UIScrollView 中跨页面拖动视图

Dragging a view across pages in an infinite UIScrollView

我在无限滚动视图的子类中跨页面拖动视图时遇到问题,因为一旦调用 viewWillLayoutSubviews 方法,视图就会卡在 0,0 坐标处。这是完整图片:

我有一个 UIScrollView 的自定义子类(启用分页),它保留一个索引,每次滚动时,它都会向其数据源询问给定索引的新视图。它从 [-1][0][1] 开始,用户只能看到 [0]。一旦用户向右滚动,[-1] 将从超级视图中删除,[0][1] 移动,页面 [2] 生成以提供 [0][1][2]。这非常有效,因为我将它用作无限滚动的日历。在此日历中,我希望能够跨周拖动约会。这是使用 UIGestureRecogniser 完成的 - 用户将约会视图保持 1 秒,这会触发 UIGestureRecogniser,然后我使用 [gesture locationInView:self] 更新约会视图的位置。

当用户拖动到视图的一侧时,滚动条会移动以显示下一页。由于约会视图是它们所属页面的子视图,这意味着我需要将约会移动到滚动条本身 ([scroll addSubview:appointmentView];) 以保持 UIGestureRecogniser 正常工作。然而,由于约会视图的原始位置是使用自动布局给出的,我无法用 [appointmentView removeFromSuperview]; 删除 parent 约束,因为它会停止 UIGestureRecogniser,我必须循环遍历所有 parent 约束并检查 firstItemsecondItem 是否等于 appointmentView。同样,这在原始页面内滚动时效果很好,尽管 appointmentView 现在是滚动的子视图而不是页面。

此时用户将 appointmentView 拖到一边,我的滚动条移动到显示下一周(每页显示一周)。然而,这一次,appointmentView briefly 瞬间移动到 (0,0),但是 UIGestureRecogniser 仍在工作,所以如果我继续移动手指,appointmentView 将 return 在屏幕上移动。此时,假设appointmentView来自第0页,它的页面在左边,居中的页面是第1页——[0][1][2].

问题终于来了:如果用户再向右移动一周,appointmentView 的原始页面(第 0 页)将被删除,因为滚动现在显示 [1][2][3] 并且appointmentView 跳转到滚动的 (0,0) 并且 UIGestureRecogniser 立即终止而没有 运行 通过其选择器,状态为 UIGestureRecogniserStateEnded.

我 99.9% 确定没有剩余的 parental 约束 link 将 appointmentView 到其原始 parent 第 0 页,这意味着我不知道为什么删除第 0 页会导致此行为。 appointmentView 仅对其自身(宽度和高度)及其子视图(视图内的标签)有约束,这意味着布局视图不应影响 appointmentView 的位置;然而...

我目前的想法:

  1. 我知道,如果我创建一个全新的 appointmentView 并将其直接添加到卷轴中,这样它就不会 link 到一周页面,它可以正常运行,没有任何问题。这意味着如果有办法以编程方式触发 UIGestureRecogniser,我可以简单地执行以下操作。当用户按住 appointmentView 一秒钟时,我可以删除旧的 appointmentView,创建一个新的并将其添加到同一位置,触发它的 UIGestureRecogniser 然后简单地跟随用户的手指使用新 appointmentView。但是,如果用户不将手指从屏幕上移开,我看不到执行此操作的方法。
  2. 也许我仍然以某种方式忘记了一些 parent 约束,这些约束导致 appointmentView 在其原始 parent 被删除时变得疯狂,但我不明白这怎么可能.它只有 4 个约束条件:x 坐标基于页面宽度的分数和约会日期; y坐标基于页面高度的分数和约会的开始时间;宽度作为页面宽度的一部分;高度作为页面高度的一部分。我清楚地删除了所有这 4 个,并将 translatesAutoresizingMaskIntoConstraints 设置为 false
  3. 放弃在角落里哭泣

如有任何意见,我们将不胜感激。

我设法解决了问题,问题出现在释放原始父视图时,所以我只是在整个移动过程中将其保存在一个变量中,并在拖动完成后释放它。