2017-07-30 257 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(_:)即可。这将告诉你哪个图层被点击。

(当然,它甚至会更好使用子视图代替层中的视图可以检测触摸;层不能。)