2016-02-26 71 views
0

簡而言之,與在scrollView中使用平移手勢相關的問題。在UIScrollView中Swift的UIPanGesture

  1. 我有一個畫布(這是一個UIView的本身,而是個頭大)我在哪裏繪製超過他們每個人的啓用平移手勢(每個小的UIView對象我說的是,使用做一些UIView的對象另一個UIView類)。

  2. 現在畫布的高度和寬度可以更大......可以根據用戶輸入更改畫布。

  3. 所以爲了實現這個目的,我把canvas放在了UIScrollView中。現在畫布正在平穩增加或減少。

  4. 畫布上那些微小的UIView對象也可以旋轉。

現在的問題。

  1. 如果如果不滾動視圖裏面,然後在畫布內的每個UIView的對象是高檔運動,我不改變畫布大小(靜態),即,一切都工作得很好用下面的代碼。

  2. 如果畫布在UIScrollView中,那麼畫布可以向右滾動?現在在scrollview中,如果我平移畫布上的UIView對象,那麼這些小UIView對象不會跟隨手指的觸摸,而不是在觸摸在畫布上移動時在另一個點上移動。

N.B. - 不知怎的,我發現我需要在任何子視圖觸摸時禁用滾動視圖的滾動。爲此,我已經實現了NSNotificationCenter以將信號傳遞給父視圖控制器。

這是代碼。

此功能被父的viewController類內部定義

func canvusScrollDisable(){ 
    print("Scrolling Off") 
    self.scrollViewForCanvus.scrollEnabled = false 
} 
func canvusScrollEnable(){ 
    print("Scrolling On") 
    self.scrollViewForCanvus.scrollEnabled = true 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 
    notificationUpdate.addObserver(self, selector: "canvusScrollEnable", name: "EnableScroll", object: nil) 
    notificationUpdate.addObserver(self, selector: "canvusScrollDisable", name: "DisableScroll", object: nil) 
} 

這是子視圖類畫布

import UIKit 

class ViewClassForUIView: UIView { 
let notification: NSNotificationCenter = NSNotificationCenter.defaultCenter() 

var lastLocation: CGPoint = CGPointMake(0, 0) 
var lastOrigin = CGPoint() 
var myFrame = CGRect() 
var location = CGPoint(x: 0, y: 0) 
var degreeOfThisView = CGFloat() 
override init(frame: CGRect){ 
    super.init(frame: frame) 

    let panRecognizer = UIPanGestureRecognizer(target: self, action: "detectPan:") 
    self.backgroundColor = addTableUpperViewBtnColor 
    self.multipleTouchEnabled = false 
    self.exclusiveTouch = true 
} 

required init?(coder aDecoder: NSCoder) { 
    fatalError("init(coder:) has not been implemented") 
} 

func detectPan(recognizer: UIPanGestureRecognizer){ 
    let translation = recognizer.translationInView(self.superview!) 
    self.center = CGPointMake(lastLocation.x + translation.x, lastLocation.y + translation.y) 
    switch(recognizer.state){ 
    case .Began: 
    break 
    case .Changed: 
    break 
    case .Ended: 
     notification.postNotificationName("EnableScroll", object: nil) 
    default: break 
    } 
} 

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    notification.postNotificationName("DisableScroll", object: nil) 
    self.superview?.bringSubviewToFront(self) 
    lastLocation = self.center 
    lastOrigin = self.frame.origin 
    let radians:Double = atan2(Double(self.transform.b), Double(self.transform.a)) 
    self.degreeOfThisView = CGFloat(radians) * (CGFloat(180)/CGFloat(M_PI)) 
    if self.degreeOfThisView != 0.0{ 
     self.transform = CGAffineTransformIdentity 
     self.lastOrigin = self.frame.origin 
     self.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_4))    
    } 
    myFrame = self.frame 
    } 

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    notification.postNotificationName("EnableScroll", object: nil) 
    } 
    } 

現在滾動視圖是完全每當一個禁用其滾動UIView對象的觸摸是在scrollview內部的畫布上進行的,但有時候這些UIView對象是ar e沒有正確地跟隨畫布/屏幕上的觸摸位置。

我使用的是Swift 2.1和Xcode 7,但任何人都可以告訴我使用Objective-c/Swift的解決方案或丟失的東西嗎?

+0

請嘗試[this](http://stackoverflow.com/a/23841224/2710486)? – zcui93

+0

@ zcui93感謝隊友的幫助...讓我的嘗試,讓你知道.. :) – Tuhin

回答

1

你在哪裏設置lastLocation?我認爲使用locationInView並自行計算翻譯會更好。然後在觸發該方法的每個事件上保存lastLocation

此外,您也可能想要處理取消狀態以及重新開啓滾動。

雖然這看起來有點麻煩。通知可能不是您的案例中的最佳主意,也不是將子標記上的手勢識別器。我認爲你應該有一個處理所有這些小觀點的觀點;它還應該有一個可以同時與其他識別器交互的手勢識別器。當手勢被識別時,它應該檢查是否有任何子視圖被擊中並決定是否應該移動它們中的任何一個。如果應該移動,則使用委託報告必須禁用滾動。如果沒有,則取消識別器(禁用+啓用)。同樣在大多數情況下,你在scrollview上放置的東西都是可移動的,你通常需要一個長按手勢識別器而不是一個平移手勢識別器。只需使用該設備並設置一些非常小的最小按壓時間。請注意,此手勢的工作原理與平移手勢完全相同,但可能會有一小段延遲被檢測到。這在這種情況下非常有用。

更新(該體系結構):

層次結構應該是:

視圖控制器 - >滾動型 - >帆布視圖 - >小的觀點

畫布視圖應該包含手勢識別控制小視圖。當手勢開始時,您應該通過遍歷子視圖並檢查它們的框架是否包含點來檢查是否有任何視圖被其位置命中。如果是這樣,它應該開始移動命中的小視圖,它應該通知它的代表它已經開始移動它。如果不是,它應該取消手勢識別器。

由於畫布視圖具有自定義委託,因此它是視圖控制器應實現其協議並將其自身作爲委託分配給畫布視圖。當畫布視圖報告視圖拖動已經開始時,它應該禁用滾動視圖滾動。當畫布視圖報告它已停止移動視圖時,它應該重新啓用滾動視圖的滾動。

  • 創建這種類型的視圖層次
  • 的創建畫布視圖,其中包括「並開始拖動」的自定義協議和「沒結束拖動」
  • 當視圖控制器變爲活動分配自作爲代表到畫布視圖。實現2種方法來啓用或禁用滾動視圖的滾動。
  • 畫布視圖應該爲自己添加一個手勢識別器,並且應該包含所有小型可移動子視圖的數組。識別器應該能夠與其他識別器同時通過其代表進行交互。
  • 畫布手勢識別器目標應該開始檢查是否有任何小視圖被擊中並將其保存爲屬性,它還應該保存手勢的當前位置。當手勢改變時,它應該根據最後和當前手勢位置移動抓取視圖,並將當前位置重新保存到屬性。當手勢結束時,它應該清除當前拖動的視圖。在開始和結束時,它應該調用委託來通知狀態的變化。
  • 取決於報告給委託的畫布視圖,禁用或啓用視圖控制器中的滾動。

我認爲這應該是全部。

+0

感謝您的想法..是啊!這些子視圖在稱爲畫布的超視圖類型內。畫布在scrollview裏面...如果可能的話,你可以給一些解釋或者一些sudo類型的代碼或者可能是一個小傻瓜... – Tuhin

+0

檢查編輯 –

+0

Cooll ... !!!!!!只是酷的隊友..沒有你的努力的話...順便說一句,我已經解決了關於視圖的一般問題不是通過使用你的想法在屏幕上觸摸「你在哪裏設置最後的位置?我認爲這會更好你可以使用locationInView並自己計算翻譯,然後在每一個觸發該方法的事件上保存lastLocation。「.....只是給出答案+1,因爲它很酷且清晰...... :) – Tuhin

相關問題