假设我有以下视图层次结构;
这些视图实际上是ShinobiCharts,它们是UIView的子类。 View1充当用户可以触摸的主图表(捏,平移,长按等)。该视图依次控制其他视图(View2,View3等)与特定的依赖于触摸的属性(用户平移View1,因此视图2和3 ......必须相应地操作并平移)。 但是,一旦用户滚动UIScrollView,View1可能会从屏幕上消失,只留下视图2,3等可见,这些视图没有相应的手势识别器,因此用户无法再与图表交互,不好用户体验。 我确定也可以为这些附加图表添加识别器,但是在收缩期间,这意味着两个手指必须位于单个视图内,用户不能只是触摸他想要的位置以便再次捏合和缩放,糟糕的用户体验。
简而言之,我需要某种覆盖UIScrollView整个内容区域的触摸拦截器,以便当用户捏或平移时,相应的触摸将被转发到主图表(View1),而这反过来可以更新其他子视图。 应始终可以垂直滚动UIScrollView。
第一次实验:
我尝试将透明的UIView添加到覆盖UIScrollView的ViewController。 但是,即使直接引用View1,触摸也不会被转发。
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.chartReference touchesBegan:touches withEvent:event];
}
我不确定这是否是实现此目的的正确方法。
第二次实验:
在UIScrollView中禁用图表子视图上的userInteraction,并将我自己的捏合和平移手势(在UIViewController中)添加到UIScrollView。
有关的问题; 1. UIScrollView不再滚动。 2.如何将这些手势转发到View1?
我担心此时无法提供更多示例代码,因为还没有太多相关代码可供展示。
修改 实验二小注; 手势识别器已添加如下;
UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGesture:)];
pinchGestureRecognizer.cancelsTouchesInView = NO;
[scrollView addGestureRecognizer:pinchGestureRecognizer];
已启用UIViewController上的同时手势识别;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
修改
实验2的问题2已经解决。我没有为pan / pinch手势设置正确的委托。 D'哦!
剩下的是如何转发捏/手势。
答案 0 :(得分:1)
您可以将透明视图置于其他视图之上。但是,您需要重写一个方法。
您想要在透明视图上覆盖hitTest:withEvent。遍历响应者链时使用此方法以查看哪个视图处理特定区域中的触摸。如果视图处理该触摸,则返回Itself。如果它想将它传递给它下面的下一个视图,它将返回nil。如果它知道另一个视图处理触摸,它可以返回该视图。
因此,在您的情况下,如果该点位于顶部透明视图的目标区域中,则返回view1。然后应该调用View1的手势识别器。
示例强>:
InterceptorView是一个位于scrollView顶部的透明视图。 TargetView是scrollView中的一个视图,并附有一个TapGestureRecognizer。
class InterceptorView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
@IBOutlet weak var targetView1: UIView?
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
print("[Interceptor] Testing point: \(point) ")
if self.pointInside(point, withEvent: event) {
println("Hit")
return targetView1
}
else {
println()
return nil;
}
}
}
-
class TargetView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
@IBAction func handleGesture(gestureRecognizer: UIGestureRecognizer) {
let location = gestureRecognizer.locationInView(self)
print("[TargetView] Got gesture. Location \(location) ")
if (pointInside(location, withEvent: nil)) {
println("Inside");
}
else {
println("Outside");
}
}
}
这是项目: https://github.com/annabd351/GestureForwarding
(那里还有一些其他东西,但它有效!)