我试图构建一个复杂的分离视图容器控制器,它有利于两个可变高度的容器,每个容器都有自己的嵌套视图控制器。父控制器上有一个全局平移手势,允许用户拖动视图容器中的任何位置,并上下滑动视图之间的“分隔线”。它还具有将扩大任一视图(或复位分隔位置)的一些智能位置阈值检测逻辑:将父容器的平移手势移交到嵌套的UICollectionView
这工作得很好。还有很多代码可以用来构建这个代码,我很乐意分享这些代码,但我不认为它是相关的,所以暂时忽略它。
现在我想通过增加集合视图的底部视图使事情变得复杂:
我已经能够解决它,这样我可以滚动拆分视图了一个决定性的平移手势,并通过快速轻弹手指来滚动集合视图(一种轻扫手势,我想它是?),但这是一种非常不平凡的体验:您无法平移视图并滚动集合同时观看,并期望用户持续复制类似但不同的手势以控制视图太难以进行交互。
为了尝试解决这个问题,我已经尝试了几种代表/协议解决方案中,我检测拆分视图除法器的位置和使能基于是否底部上的集合视图/禁用canCancelTouchesInView
和/或isUserInteractionEnable
视图完全展开。这个工程到一个点,但不是在以下两种情况下:
- 当拆分视图分频器是在其默认位置,如果用户锅高达船底视图完全展开,然后扫视保持,收集视图应该开始滚动,直到手势结束。
- 当拆分视图分隔符位于顶部(底部容器视图已完全展开)并且顶部的集合视图是而不是时,如果用户平移,集合视图应该滚动而不是移动拆分视图分隔符,直到收集视图到达顶部位置,此时分割视图应该返回到其默认位置。
这里是说明此行为的动画:
鉴于此,我开始思考解决问题的唯一方法是通过在拆分视图中创建一个委托方法它在底部视图处于最大高度时告诉集合视图,然后可以拦截父级的平移手势或将屏幕接触转发到集合视图?但是,我不知道该怎么做。如果我在解决方案的正确轨道上,那么我的问题就是:如何将平移手势转发或切换到集合视图,并使集合视图以与捕获触摸相同的方式进行交互首先呢?我可以用pointInside
或touches____
方法做些什么吗?
如果我不能这样做,我还能怎么解决这个问题?
更新赏金猎人:我有一些零散的运气创建的集合视图的委托方法,并调用它拆分视图容器上设置属性shouldScroll
,由我使用一些摇摄方向,定位信息以确定滚动视图是否应滚动。然后,我在的UIGestureRecognizerDelegate
gestureRecognizer:shouldReceive touch:
委托方法返回该值:
// protocol delegate
protocol GalleryCollectionViewDelegate {
var shouldScroll: Bool? { get }
}
// shouldScroll property
private var _shouldScroll: Bool? = nil
var shouldScroll: Bool {
get {
// Will attempt to retrieve delegate value, or self set value, or return false
return self.galleryDelegate?.shouldScroll ?? self._shouldScroll ?? false
}
set {
self._shouldScroll = newValue
}
}
// UIGestureRecognizerDelegate method
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return shouldScroll
}
// ----------------
// Delegate property/getter called on the split view controller and the logic:
var shouldScroll: Bool? {
get {
return panTarget != self
}
}
var panTarget: UIViewController! {
get {
// Use intelligent position detection to determine whether the pan should be
// captured by the containing splitview or the gallery's collectionview
switch (viewState.currentPosition,
viewState.pan?.directionTravelled,
galleryScene.galleryCollectionView.isScrolled) {
case (.top, .up?, _), (.top, .down?, true): return galleryScene
default: return self
}
}
}
这工作,当你开始滚动就OK了,但一旦滚动的集合视图能不能很好地执行,因为滚动手势几乎总是覆盖平移手势。我想知道我是否可以用gestureRecognizer:shouldRecognizeSimultaneouslyWith:
连线,但我还没有。
你能分享你的代码来测试这种行为吗?在你提到的两种情况中,似乎collectionView应该消耗触摸事件,直到它的水平偏移达到它看起来相当简单的边界。 – Lukas
@Lukas我可以,但我不确定它是否真的能帮助解决问题 - 这是因为很多内置IB的IB约束,并且因为您已经知道我有检测代理的方法可以完全按照您的方式已经描述过:“当水平偏移达到其上边界时,collectionView应该消耗触摸事件。”不过,如果你想要一些代码,我可以添加一些''__ _(ツ)_ /' – brandonscript