2014-11-21 22 views
2

假设我有以下视图层次结构;UIScrollView带有用于contentSize的触摸拦截器来控制子视图

enter image description here

这些观点实际上是ShinobiCharts,这是UIView的子类。视图1是用户可以触摸的主要图表(捏,平移,长按等)。该视图依次控制其他视图(视图2,视图3等)与特定的触摸相关属性(用户平移视图1,因此视图2和3 ...必须相应地执行并平移)。 但是,一旦用户滚动UIScrollView,View1可能会从屏幕上消失,只留下可见的视图2,3等,这些视图没有相应的手势识别器,因此用户无法再与图表交互,糟糕的用户体验。 我当然也可以在这些附加图表中添加识别器,但是在捏合过程中,这意味着两个手指必须位于单个视图内,用户不能只触摸到他想要捏合和缩放的位置,再次,糟糕的用户体验。为了简化事情,我需要一些触摸拦截器,覆盖UIScrollView的整个内容区域,以便当用户捏或平移时,相应的触摸将被转发到主图表(视图1),然后轮流可以更新其他子视图。应始终可以垂直滚动UIScrollView。

实验一:

我已经尝试添加一个透明的UIView到覆盖的UIScrollView的视图控制器。 但是,即使直接引用View1,触摸也不会被转发。

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [self.chartReference touchesBegan:touches withEvent:event]; 
} 

我不太确定这是否是正确的方法来实现这个反正。

第二个实验:

在图表子视图的UIScrollView中禁用的用户交互,并添加自己的捏和平移手势(在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

你尝试了'UIScrollView'缩放功能。它支持默认捏缩放,你只需要提供将被缩放的视图,所以我认为你只需要确定屏幕上的哪个视图并将其传递给'UIScrollView'。 – danypata 2014-11-21 12:13:54

+0

放大UIScrollView看起来更像是一个简单缩放UIScrollView的子视图的解决方案,因此可以修改它们的大小。这不是我想要的。尺寸必须保持不变,因为只有我的UIViews的内容需要改变,而这又由ShinobiChart本身处理。 – AlBirdie 2014-11-21 12:21:05

回答

1

您很接近将透明视图置于其他视图之上。但是,您需要重写另一个方法。

你想覆盖透明视图上的hitTest:withEvent。在遍历响应者链时使用此方法,以查看哪个视图处理特定区域中的触摸。如果视图处理该触摸,它将返回Itself。如果它想将它传递给它下面的下一个视图,则返回nil。如果它知道另一个视图处理该触摸,它可以返回该视图。

因此,对于您的情况,如果该点位于顶部透明视图的目标区域中,则返回view1。然后应该调用View1的手势识别器。

InterceptorView是其位于上滚动视图的顶部上的透视图。 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

(还有一些其他的东西在那里,但它的作品!)

+0

不幸的是,这不起作用。 View1没有收到触摸。 UIScrollView可能会阻止它们吗? – AlBirdie 2014-11-24 10:26:19

+0

我只是试图把一个“拦截器”视图放在scrollView的顶部。似乎工作 - 我做了一个示例项目。 (请参阅编辑答案) – 2014-11-24 18:55:18

+0

您在Github上的项目不包含任何源代码。我的代码看起来和你的完全一样,事实上,touchBegin/Moved在TargetView的子类中被调用(我不能直接改变TargetView,因为它是第三方库的一部分。是的,我需要TargetView拿起手势,而这种手势不适用于这种触摸转发方法,或者至少不是现在提供的代码。 – AlBirdie 2014-11-25 09:37:09