January 14, 2021

312 words 2 mins read

Hit test 사용하기

Hit test 사용하기

Hit test 의 활용 예시를 소개합니다


👉🏻👉🏻👉🏻 Hit-testing과 Hit-testing이 이벤트를 처리할 UIView 객체를 찾는 과정과 로직에 대한 설명은 이전 포스팅 을 확인해주세요! 👈🏻👈🏻👈🏻

< 📑 목차 >

  1. 터치 면적 넓히기
  2. 터치 이벤트를 아래 view로 전달하기



안녕하세요! HitTest의 사용 예시에 대해 소개하겠습니다. 아는 분이 HitTest 키워드를 알려주셔서 흥미로워서 공부해봤는데 지난 포스트와 이번 포스트 모두 재밌는것 같아요 👻

Hit test는 그럼 언제 사용할까요?

A view에서 처리하려는 터치 이벤트가 해당 터치 이벤트 시퀀스의 모든 단계에 대해 B view로 리다이렉트 되어야 할 때 hitTest:withEvent: 메서드를 재정의해서 사용할 수 있습니다.

터치 면적 넓히기(Increasing view touch area)

뷰의 터치 영역이 bound보다 커야 하는 경우 hitTest:withEvent: 메서드를 재정의해서 사용할 수 있습니다. 아래 코드는 사이즈가 20x20인 UIView의 터치 영역을 10 point씩 증가시키는 예시입니다.

Increasing touch area

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    if !isUserInteractionEnabled || isHidden || alpha <= 0.01 {  return nil }
 
    let touchRect = bounds.insetBy(dx: -10, dy: -10)
    if touchRect.contains(point) {
        for subview in subviews.reversed() {
            let convertedPoint = subview.convert(point, from: self)
            if let hitTestView = subview.hitTest(convertedPoint, with: event) {
                return hitTestView
            }
        }
        return self
    }
    return nil
}

터치 이벤트를 아래 view로 전달하기(Passing touch events through to views below)

view hierarchy 뷰 계층에서 가장 최상단에 있는 view가 터치 이벤트를 받는 것이 아니라 그 아래에 있는 view가 터치 이벤트를 받아야 하는 경우가 있습니다. 대표적인 예 중 하나는 TableView Cell 안에 있는 버튼이 있겠네요! 이럴 때 최상단 view의 custom class를 만들어서 아래와 같이 hitTest 메서드를 오버라이드 해준다면 최상단 바로 아래에 있는 view 가 터치 이벤트를 받게 할 수 있습니다.

  override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
      let hitView: UIView? = super.hitTest(point, with: event)
      if (self == hitView) { return nil }
      return hitView
  }

화면을 만들다보면 view를 여러 layer로 쌓아서 만들거나 뷰 계층이 복잡해지는 경우가 있는데, 이런 경우 hit test를 통해서 터치 이벤트를 받을 UIView 객체를 지정해줄 수 있는 점이 편한 것 같아요! 👍🏻

참고

  1. Hit-Testing in iOS

  2. iOS/swift. hitTest 이용하기