ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [레인스톤 iOS] 원하는 view를 기준으로 view frame 바꿔보기(feat. convert)
    iOS 실무 꿀팁 2022. 3. 19. 13:55
    반응형

    안녕하세요:)

    iOS 개발자로 일하고 있는 레인스톤입니다.

     

    오늘은 특정뷰의 frame을 Superview가 아닌,

    Superview의 Superview,

    또는 내가 원하는 다른 view를 기준으로 얻어내는 법을 알아보겠습니다.

     

    말로 설명하려니까 너무 어렵네요 ㅠㅠ

     

    뭘 하고자 하는 거냐면요

    UIViewController의 view의 subview로 검은색 stackview를 추가했습니다.

    그리고 stackView의 subView로 파란색, 빨간색, 초록색 button을 추가했습니다.

    이 상태에서 각 button을 탭할 때마다 frame을 출력해볼까요?

     

    (0.0, 0.0, 100.0, 50.0) // 파란색
    (104.0, 0.0, 100.0, 50.0) // 빨간색
    (208.0, 0.0, 100.0, 50.0) // 초록색
    
    // (x, y, width, height)

     

    쨘 ~ 아무 문제없이 출력됐습니다.

    그런데 만약에 파란색 button의 위치를 stackView 기준이 아니라

    stackView의 superView 기준으로 알고 싶다면 어떻게 해야할까요?

     

    (33.66666666666666, 381.0, 308.0, 50.0) // 검은색 stackView frame

     

    즉 파란색 button의 x값이 stackView와 같이 33.6666으로 나오게 하는 방법입니다.

     

    Convert

    이 문제는 Convert를 활용해서 쉽게 해결이 가능합니다.

     

    view.convert(button.frame, from: stackView)

     

    • view→ 향후frame의 기준이 될 View
    • button.frame →  얻고자하는 View의 frame
    • stackView → 현재 frame의 기준이 되는 View

     

    (33.66666666666666, 381.0, 100.0, 50.0) // 파란색
    (137.66666666666666, 381.0, 100.0, 50.0) // 빨간색
    (241.66666666666666, 381.0, 99.99999999999997, 50.0) // 초록색

     

    쨘 ~ 이렇게하면 원하는 결과를 얻을 수 있습니다.

     

    이걸로 뭘 할 수 있는데?

     

    이렇게 각 button을 클릭할 때마다 stackView가 아닌

    UIViewController의 view에서 해당 button의 위치에 맞게 특정 view를 보여줄 수 있습니다:)

     

    끗!

     

    코드

    import UIKit
    import SnapKit
    import Then
    import RxSwift
    import RxCocoa
    
    final class ViewController: UIViewController {
        
        private let stackView = UIStackView()
        private let blueButton = UIButton()
        private let redButton = UIButton()
        private let greenButton = UIButton()
        private let textLabel = UILabel()
        
        private let bag = DisposeBag()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            stackView.do {
                $0.axis = .horizontal
                $0.spacing = 4
                $0.distribution = .fillEqually
                $0.backgroundColor = .black
            }
            
            textLabel.do {
                $0.text = "저를 선택하셨군요!?"
                $0.isHidden = true
            }
            
            blueButton.do {
                $0.backgroundColor = .blue
            }
            
            redButton.do {
                $0.backgroundColor = .red
            }
            
            greenButton.do {
                $0.backgroundColor = .green
            }
            
            view.addSubview(stackView)
            view.addSubview(textLabel)
            
            stackView.snp.makeConstraints {
                $0.centerX.centerY.equalToSuperview()
            }
            
            textLabel.snp.makeConstraints {
                $0.height.equalTo(50)
                $0.leading.top.equalToSuperview()
            }
            
            [blueButton, redButton, greenButton].forEach { button in
                stackView.addArrangedSubview(button)
                
                button.snp.makeConstraints {
                    $0.width.equalTo(100)
                    $0.height.equalTo(50)
                }
                
                button.rx.tap
                    .subscribe(onNext: { [unowned self] _ in
                        self.textLabel.isHidden = false
                        
                        let frame = self.view.convert(button.frame, from: self.stackView)
                        textLabel.snp.updateConstraints {
                            $0.leading.equalToSuperview().offset(frame.minX)
                            $0.top.equalToSuperview().offset(frame.minY-50)
                        }
                    })
                    .disposed(by: bag)
            }
        }
    }
    반응형

    댓글

Designed by Tistory.