Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- Human interface guide
- 리펙토링
- RxCocoa
- 스위프트
- Clean Code
- 애니메이션
- uiscrollview
- UITextView
- MVVM
- 리팩토링
- Refactoring
- clean architecture
- rxswift
- HIG
- 리펙터링
- swiftUI
- Observable
- 클린 코드
- tableView
- ribs
- SWIFT
- UICollectionView
- uitableview
- collectionview
- ios
- swift documentation
- Protocol
- Xcode
- map
- combine
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] UIView 화면에 보여지는 이벤트 구하는 방법(#스크롤 뷰 등장, #viewAppear, #convert(_:to:), #intersects) 본문
iOS 응용 (swift)
[iOS - swift] UIView 화면에 보여지는 이벤트 구하는 방법(#스크롤 뷰 등장, #viewAppear, #convert(_:to:), #intersects)
jake-kim 2023. 10. 13. 01:34
ViewAppear 이벤트 아이디어
- UIViewController는 viewWillAppear와 같은 뷰컨트롤러가 보이기 직전에 델리게이트 메소드가 있지만, UIView는 존재 x
- UIView에서 viewAppear와 같은 메소드가 있다면, 특정 뷰가 등장했을때 파악이 가능
- 등장했을때 해당 뷰의 frame값을 구하여, 이 뷰와 현재 화면의 bounds를 intersects하여 구하면 쉽게 파악이 가능
- * intersects: 인자로 들어온 rect값에 호출한 instance의 bounds가 겹치는지 파악할때 사용하는 메소드
- CGRect의 확장으로 정의된 함수
extension CGRect {
public func intersects(_ rect2: CGRect) -> Bool
}
viewAppear구현
* 예제 코드 준비) UIScrollView + UIStackView 안에 UILabel이 여러개 있는 형태
- 코드
import UIKit
class ViewController: UIViewController {
private let label = {
let label = UILabel()
label.font = .systemFont(ofSize: 24, weight: .regular)
label.numberOfLines = 0
label.text = "보이는중"
label.isHidden = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let scrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let stackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(label)
view.addSubview(scrollView)
scrollView.addSubview(stackView)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: view.leadingAnchor),
label.trailingAnchor.constraint(equalTo: view.trailingAnchor),
label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
])
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
])
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
stackView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width),
])
(0...100)
.forEach { int in
let label = {
let l = UILabel()
l.text = String(int)
if int == 70 {
l.text = String(int) + " <"
}
l.textAlignment = .center
l.textColor = .black
l.font = .systemFont(ofSize: 24)
return l
}()
stackView.addArrangedSubview(label)
}
}
}
- 스크롤 될 때마다 프레임을 체크하여, 현재 보이는지 판단할 visibleInScreen 프로퍼티 준비
- screen의 bounds에 보여지는지 확인할 뷰의 bounds값을 convert(_:to:)로 window기준, 상대 frame으로 변환 - convert(_:to:) 함수 구체적인 개념은 이전 포스팅 글 참고
- 이 frame을 현재 화면 UIScreen.main.bounds와 겹치는지 intersects(_:)함수를 사용하여 비교
extension UIView {
var visibleInScreen: Bool {
guard !isHidden, window != nil, 0 < alpha else { return false }
let screenBounds = UIScreen.main.bounds
let viewFrame = convert(bounds, to: nil)
return viewFrame.intersects(screenBounds)
}
}
- 이 함수를 스크롤 될때마다 체크하여, 보여질때 표시할 UILabel의 hidden값을 변경
scrollView.delegate = self
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: overView.frame.minY + labels[71].frame.height)
label.isHidden = !labels[71].visibleIn(bounds: bounds)
}
}
(결과)
응용 - A frame에 B뷰가 속하는지 판단하는 방법
- 위에서 UIScreen.main.bounds 기준으로 판단했으므로, 이제 A frame값을 사용하여 A frame에 B뷰가 보이는지 판단이 가능
extension UIView {
func visibleIn(bounds: CGRect) -> Bool {
guard !isHidden, 0 < alpha else { return false }
let viewFrame = convert(self.bounds, to: nil)
return viewFrame.intersects(bounds)
}
}
* 전체 코드: https://github.com/JK0369/ExEventViewAppear
* 참고
https://developer.apple.com/documentation/uikit/uiview/1622442-convert
https://developer.apple.com/documentation/coregraphics/1454747-cgrectintersectsrect
'iOS 응용 (swift)' 카테고리의 다른 글
Comments