2017-07-30 13 views
1

我創建一個可重複使用的多態開關從UIControl看起來類似於默認UISwitch,有兩個以上的狀態延伸的邊界之外的觸摸。該實現就像添加CALayers爲每個狀態和一個額外的層來突出顯示UIView上的選定狀態。的iOS:無法檢測到的CALayer

的UI看起來像這樣

multi state switch

的問題是,當用戶敲擊就像圖像中顯示的平方境外我都認不出的狀態的觸摸。有一個簡單的便利方法(getIndexForLocation),我添加了返回所選狀態的索引,給定觸點。使用返回的選定索引,我將高亮度指示符的位置移動到所選狀態的中心位置。方法UIControl的與最後的觸摸點:

func getIndexForLocation(_ point: CGPoint) -> Int { 
    var index = selectedIndex 
    let sLayers = self.controlLayer.sublayers 
    for i in 0..<totalStates { 
     if sLayers![i].frame.contains(point) { 
      index = i 
     } 
    } 
    return index 
} 

上述方法從endTracking(用於事件的觸摸)調用。

我怎樣才能改變這種方法,讓我能得到觸摸/選擇狀態的指標,即使用戶已對圖像周圍的感動。觸摸區域可以近似位於狀態圖像中心頂部的高亮圓圈區域。

self.controlLayer是其子層的所有國家和高亮指示燈容器層。

,增加了不如下

func performSwitch(to index: Int) ->() { 
    guard selectedIndex != index else { 
     return 
    } 

    let offsetDiff = CGFloat((index - selectedIndex) * (stateSize + 2)) 
    let oldPosition = indicatorPosition 
    indicatorPosition.x += offsetDiff 
    let newPosition = indicatorPosition 

    let animation: CABasicAnimation = CABasicAnimation(keyPath: "position") 
    animation.timingFunction = CAMediaTimingFunction(controlPoints: 0.785, 0.135, 0.15, 0.86) 
    animation.duration = 0.6 
    animation.fromValue = NSValue(cgPoint: oldPosition!) 
    animation.toValue = NSValue(cgPoint: newPosition!) 
    animation.autoreverses = false 
    animation.delegate = self 
    animation.isRemovedOnCompletion = false 
    animation.fillMode = kCAFillModeForwards 


    self.selectedIndex = index 
    self.stateIndicator.add(animation, forKey: "position") 
} 

任何幫助提供與所選擇的索引位置的動畫的方法,將不勝感激。

回答

0

你這麼說if sLayers![i].frame.contains(point)測試。因此,最簡單的解決方案是讓每個「按鈕」的框架更大 - 足夠大以包含您希望作爲該「按鈕」可觸摸的整個區域。請記住,繪圖可以很小,即使框架大。

而且,正如順便說一句,你的代碼是愚蠢的,因爲你基本上是執行命中測試。對圖層進行命中測試是內置的,因此,一旦您的圖像正確無誤,您只需在超級圖層上調用hitTest(_:)即可。這將告訴你哪個圖層被點擊。

(當然,它甚至會更好使用子視圖代替層中的視圖可以檢測觸摸;層不能。)