2014-11-21 52 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