[TIL] iOS 입문 주차 과제 : 계산기 앱 만들기 day.05

Emily·2024년 11월 21일
2

CalculatorApp

목록 보기
10/11
post-thumbnail

Scroll view 적용

before

입력값이 많아져 텍스트의 길이가 화면 너비를 넘기면, 그때부터 입력값은 자리가 없으니 ...로 표시된다. 텍스트가 축약되지 않고 입력값이 계속 표시될 수 있게 스크롤이 넣고 싶어졌다. 우선 강의에서 배운 내용에 따르면 스크롤 뷰의 내용(컨텐트 뷰)이 스크롤 뷰와 너비가 같으면 vertical, 높이가 같으면 horizontal 스크롤이 생긴다. 그걸 떠올리며 UIScrollViewMainViewController에 추가하고 레이아웃을 적용했다.

class MainViewController: UIViewController {
	private lazy var scrollView: UIScrollView = {
    	let view = UIScrollView()
        
        view.backgroundColor = .black
        view.indicatorStyle = .white	// 배경이 까마니까 스크롤은 하얗게
        
        return view
    }()
    
    private func addSubview() {
    	// inputLabel을 view에 subview로 지정했던 것을 지우고, scrollView의 subview로 지정
        view.addSubview(scrollView)
        scrollView.addSubview(inputLabel)
    }
    
    private func layout() {
    	let superView = view.safeAreaLayoutGuide
        let offset: CGFloat = 30.0
        
        NSLayoutConstraint.activate([
            // 원래 inputLabel이 갖고 있던 제약조건을 그대로 scrollView에 적용
            scrollView.leadingAnchor.constraint(equalTo: superView.leadingAnchor, constant: offset),
            scrollView.trailingAnchor.constraint(equalTo: superView.trailingAnchor, constant: -offset),
            scrollView.topAnchor.constraint(equalTo: superView.topAnchor, constant: 200),
            scrollView.heightAnchor.constraint(equalToConstant: 100),

            // inputLabel의 상하좌우 및 높이 값을 scrollView에 일치
            inputLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            inputLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            inputLabel.topAnchor.constraint(equalTo: scrollView.topAnchor),
            inputLabel.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            inputLabel.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
        ])
    }
}

여기까지 하고 실행해보니, 가로(horizontal) 스크롤이 생겼다. 그런데 두가지 개선해야 할 점이 있었다.

  1. 오른쪽 정렬이었던 inputLabel의 텍스트가 갑자기 왼쪽 정렬이 되었다. 다시 오른쪽으로 보내야 한다.
  2. 텍스트가 길어져 스크롤이 생겼을 때, 스크롤이 가장 최근에 입력된 값 쪽(오른쪽)에 위치해야하는데 맨 앞(왼쪽)에 고정되어 있다.

즉, 라벨 텍스트와 스크롤을 둘다 오른쪽으로 보내기가 미션이다. 어떻게 할 수 있을까?

01) UIScrollView 속 UILabel을 오른쪽에 붙이기


view hierarchy를 보면, label의 너비를 따로 지정하지 않았기 때문에, text의 길이에 따라 너비를 갖게 된 것을 확인할 수 있다. 그렇기 때문에 label.textAlignment = .right로 텍스트의 오른쪽 정렬을 지정했어도 소용이 없는 것이다. 저 좁은 공간 안에서 텍스트는 이미 오른쪽에 붙어있을 것이다. 스크롤 뷰 공간 내에서 오른쪽에 붙이려면 어떻게 해야할까? 스크롤 뷰가 가진 속성들을 구경하며 뭘 넣으면 좋을까 고민해본다.

Alignment라는 단어를 보자마자 이거다 싶다.

A point where the scroll view anchors content that's smaller than the scroll view's frame.
스크롤 뷰가 자신의 프레임보다 작은 컨텐트를 고정시키는(anchors : 닻을 내리는) 포인트.

밑에 디스커션을 읽어보면 좌측상단을 (0, 0)으로 하는 좌표 값이 default라고 되어있다.(내 label이 왼쪽에 붙어있는 이유) 가운데 넣고 싶다면 (0.5, 0.5)로 하라고 조언하고 있다. 그럼 우측 중앙에 넣고 싶다면?

scrollView.contentAlignmentPoint = CGPoint(x: 1, y: 0.5)


완성.

여담

AI한테 물어봤는데

contentAlignmentPointUIScrollView의 프로퍼티가 아니라는 뚱딴지 같은 소리를 하고 textAlignment = .right 이미 했는데 이거나 하라고 한다. 나보고 슬라잇 미스언더스탠딩 이러고 있네 아오 너는 휴즈 미스언더스탠딩을 하고 있어 이 자식아.

한마디 해줬다. 아니 제대로 안알려주면 어떡하냐고 내가 스스로 알아내야 되냐고😑(그렇긴 함) 하여튼 이 자식 때문에 스스로 알아내느라 좀 헤맸다.

02) 스크롤을 오른쪽 끝에 고정하기

다행이 이 부분은 클로드 친구가 조언을 주었다. 일단, scrollViewcontentSize 속성을 label과 일치시킨다.

scrollView.contentSize = CGSize(width: inputLabel.intrinsicContentSize.width, height: inputLabel.bounds.height)
// 찾아보니 intrinsicContentSize는 고유 사이즈라고 한다.

그 다음, contentOffsetx 값을 컨텐트(라벨) 너비에서 스크롤 뷰 너비를 뺀 값으로 지정해준다.

scrollView.contentOffset = CGPoint(x: scrollView.contentSize.width - scrollView.bounds.width, y: 0)

풀어서 얘기하자면 텍스트가 길어지느라 화면 밖으로 넘어간 만큼 xoffset을 반대로 주는 것이다.(-니까?) 솔직히 그렇구나 싶은거지 백퍼 이해는 안된다.

하여튼 저 두 코드를 열심히 작성한 뒤 viewDidLoad에 호출하면 안되고, viewDidLayoutSubviews라는 함수를 override하여 호출해야 한다. 이 부분은 내배캠 동기님의 포스팅을 참고하여 안 것이다. (클로드는 텍스트가 추가되는 시점에 호출하는 예시를 보여주었다.)

override func viewDidLayoutSubviews() {
	setScrollView()
}
    
private func setScrollView() {
	// 스크롤 뷰의 content size를 label size와 일치시킴
    scrollView.contentSize = CGSize(width: inputLabel.intrinsicContentSize.width, height: inputLabel.bounds.height)
        
    // 스크롤을 우측에 고정
    scrollView.contentOffset = CGPoint(x: scrollView.contentSize.width - scrollView.bounds.width, y: 0)
}

after

오른쪽에 잘 붙어있는 스크롤이 적용되었다.

profile
iOS Junior Developer

2개의 댓글

제 블로그가 소개되다니 쑥스럽네요ㅎㅎ
스크롤뷰를 적용하는 과정 재밌게 봤습니다!! 중간에 AI에게 뭐라고 하시는 부분이 인상깊네요ㅎㅎ

1개의 답글