관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Cell에서 highlighted 애니메이션 안먹는 이유 (UIScrollView, delaysContentTouches, canCancelContentTouches) 본문

iOS 응용 (swift)

[iOS - swift] Cell에서 highlighted 애니메이션 안먹는 이유 (UIScrollView, delaysContentTouches, canCancelContentTouches)

jake-kim 2023. 1. 26. 21:48

UITableViewCell안에 버튼이 있을때의 highlighted 애니메이션

  • 보통 회색 뷰의 버튼처럼 짧게 버튼을 눌러도 hilighted 색상으로 변하지만, UITableView안에 버튼이 있는 경우 (아래 흰색 뷰) hilighted 애니메이션이 안보일 정도로 짧게 동작
  • 길게 누르고 있어야 애니메이션이 highlighted 애니메이션이 동작

delaysContentTouches 프로퍼티

  • UIScrollView이 가지고 있는 프로퍼티
  • UIScrollView 위에 쌓아진 뷰들을 touch-down 했을 때, 쌓아진 뷰를 잠깐 delay하고 UIScrollView가 대신 touch-down 이벤트를 받을지 판단할때 사용
    • true인 경우 (=디폴트): 셀 위에 button이 있을때, button이 터치 이벤트를 받고나서 바로, UIScrollView가 이벤트를 받아 셀을 드래그해서 스크롤할 수 있도록 되는 것
    • faluse인 경우: 셀 위에 button이 있을때, UIScrollView가 이벤트를 받지 않고 바로 button이 이벤트를 받는 것 (대신, UIScrollView 위에 있는 뷰를 드래그 했을때 스크롤이 안먹는 현상 존재)

https://developer.apple.com/documentation/uikit/uiscrollview/1619398-delayscontenttouches

  • UIScrollView의 subview들을 선택해도, UIScrollView가 이벤트를 수신하여 subview들을 드래그했을때 UIScrollView가 이벤트를 받아 스크롤되는 원리
  • delaysContentTouches = false로 하는 경우 예시
    • 셀 위에 있는 버튼을 눌렀을때 highlighted 애니메이션을 바로 확인 가능
    • 스크롤이 안되는 현상이 존재

tableView.delaysContentTouches = false

Highlighted 애니메이션을 주고 스크롤 되는 방법

  • UITableView의 property 중 canCancelContentTouches = true로 설정하여 touchesShouldCancel(in:) 메소드 활성화한 후, 이 메소드에서 스크롤 되게끔 설정
  • touchesShouldCancel(in:): subview의 이벤트를 취소하고(=버튼의 이벤트) 드래깅을 계속 시도할지 true or false를 리턴하는 메소드

https://developer.apple.com/documentation/uikit/uiscrollview/1619387-touchesshouldcancel

  • delaysContentTouches = false로하여 버튼이 터치를 받도록 하고, touchesShouldCancel(in:)에서 터치된 뷰가 UIControl이면 무조건 true를 리턴하게하여 버튼이 highlighted 애니메이션 동작하고 바로 드래깅 되게끔 구현
    • 커스텀 tableView 추가
final class HighlightedTableView: UITableView {
    init() {
        super.init(frame: .zero, style: .grouped)
        
        delaysContentTouches = false
        canCancelContentTouches = true
    }
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    override func touchesShouldCancel(in view: UIView) -> Bool {
        if view is UIControl {
            return true // enable drag
        }
        return super.touchesShouldCancel(in: view)
    }
}

(결과)

* 전체 코드: https://github.com/JK0369/ExDelay

* 참고

https://developer.apple.com/documentation/uikit/uiscrollview/1619387-touchesshouldcancel

https://developer.apple.com/documentation/uikit/uiscrollview/1619398-delayscontenttouches

Comments