일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 파이썬중급
- 웹크롤링
- 스위프트
- 인프런파이썬강의
- IOS
- JS
- 카카오톡채팅봇
- 리프2기
- uikit
- 자바스크립트
- rxswift
- 인프런오리지널
- swift
- 우리를위한프로그래밍
- nodeJS
- 인프런강의
- 노드JS
- 토플공부수기
- Python3
- SwiftUI
- IOS프로그래밍
- 파이썬중급강의
- 프로그래머스
- 토플
- 유학토플
- 인프런
- 파이썬
- 인프런파이썬
- 파이썬웹크롤링
- 교환학생토플
- Today
- Total
먹고 기도하고 코딩하라
[UIKit] 탭한 위치가 어느 뷰의 영역 안에 있는지 확인하기 본문
1. 버튼이 아닌 일반 UIView에서 Touch up Inside 등의 탭 이벤트를 감지하려면, UITapGestureRecognizer를 뷰에 붙여줘야 한다. 또한, recognizer가 탭 이벤트를 감지했을 때 수행할 셀렉터 함수도 필요하다.
셀렉터 함수부터 만들어주자. 여기서는 tapSomewhere이라는 이름으로 만든다.
class ViewController: UIViewController {
@IBOutlet weak var dimmedBGView: UIView!
var bgViewTapGesture: UITapGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
bgViewTapGesture = UITapGestureRecognizer(target: self, action: #selector(tapSomewhere(_:)))
}
deinit {
bgViewTapGesture = nil
}
@objc func tapSomewhere(_ gesture: UITapGestureRecognizer) {
}
}
2. 뷰에 addGestureRecognizer로 recognizer를 붙여준다.
bgViewTapGesture = UITapGestureRecognizer(target: self, action: #selector(tapSomewhere(_:)))
guard let bgViewTapGesture else { return }
dimmedBGView.addGestureRecognizer(bgViewTapGesture)
3. 셀렉터 함수 내부를 작성한다. 뷰 안에 이미지뷰 expandableImageView가 있는데, 그 이미지뷰 외부 영역에 대해 탭 이벤트가 발생했을 때 뷰가 숨겨지는 작업을 하겠다.
@IBOutlet weak var expandableImageView: UIImageView!
@objc func tapSomewhere(_ gesture: UITapGestureRecognizer) {
if !expandableImageView.frame.contains(gesture.location(in: gesture.view)) {
dimmedBGView.isHidden = true
}
}
이처럼 탭 제스처의 이벤트가 일어난 영역의 좌표가 어떤 뷰 안에 포함되는지 확인하려면 frame.contains(:CGPoint)를 사용하면 된다. gesture.location(in: UIView?)는 탭 이벤트가 일어난 뷰의 좌표를 CGPoint로 돌려주기 때문에, contains(:CGPoint) 메소드를 사용할 수 있다.
이를 응용해서 이미지를 누르면 이미지가 크게 보이고 배경이 딤처리된 뷰가 화면을 덮는 등의 작업을 할 수 있다. 이미지가 아닌, 딤처리된 배경을 탭했을 때는 화면이 확대된 뷰가 숨겨지는 행위를 한다.
코드 전문은 아래와 같다. 여기서 사용한 UIImage의 extension resize 메소드는 이 블로그의 코드를 사용했다.
UIButton의 setImage를 통해 이미지를 셋팅할 때, 이미지 크기가 버튼 크기보다 크면 버튼에 constraint를 설정했더라도 그것을 무시하고 크기가 설정되기 때문에 적절한 resize는 필수다.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageButton: UIButton!
@IBOutlet weak var dimmedBGView: UIView!
@IBOutlet weak var expandableImageView: UIImageView!
let imageURLStr: String = "<https://images.unsplash.com/photo-1535957998253-26ae1ef29506>"
var bgViewTapGesture: UITapGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
imageURLStr.loadAsyncImage { [weak self] image in
guard let self else { return }
let resizedImage: UIImage? = image?.resize(targetSize: .init(width: UIScreen.main.bounds.width - 100, height: ((UIScreen.main.bounds.width - 100) / 3) * 4))
imageButton.setImage(resizedImage, for: .normal)
expandableImageView.image = image
}
bgViewTapGesture = UITapGestureRecognizer(target: self, action: #selector(tapSomewhere(_:)))
guard let bgViewTapGesture else { return }
dimmedBGView.addGestureRecognizer(bgViewTapGesture)
}
deinit {
bgViewTapGesture = nil
}
@IBAction func onImageButton(_ sender: UIButton) {
dimmedBGView.isHidden = false
}
@objc func tapSomewhere(_ gesture: UITapGestureRecognizer) {
if !expandableImageView.frame.contains(gesture.location(in: gesture.view)) {
dimmedBGView.isHidden = true
}
}
}
extension String {
func loadAsyncImage(_ completion: @escaping (UIImage?) -> ()) {
guard let url: URL = URL(string: self) else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data,
response != nil,
error == nil else { return }
DispatchQueue.main.async {
completion(UIImage(data: data))
}
}.resume()
}
}
extension UIImage {
func resize(targetSize: CGSize) -> UIImage? {
let newRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height).integral
UIGraphicsBeginImageContextWithOptions(newRect.size, true, 0)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.interpolationQuality = .high
draw(in: newRect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
References
'앱 > Swift' 카테고리의 다른 글
[UIKit] status bar, home indicator 배경색 변경하기 (0) | 2023.08.24 |
---|---|
[UIKit] Status bar 폰트 색상 동적으로 변경하기 (0) | 2023.08.17 |
[UIKit] 뷰의 동적 넓이 변경에 GradientLayer 대응하기 (0) | 2023.08.03 |
[UIKit] Data(contentsOf:) 대신 URLSession으로 이미지 불러오기 (0) | 2023.07.23 |
[Swift] 백준의 모든 입출력 처리하기 (0) | 2023.07.15 |