영화관 앱의 세부 화면을 맡게 되어서 UI작업을 시작했다.
우선, MovieDescriptionView
는 영화 설명을 보여주는 뷰로,
기본적으로 긴 텍스트를 다루기 위해 UILabel
을 사용했다.
하지만 텍스트의 양이 많아지면 화면에 전부 보이지 않기 때문에,
사용자가 "더보기" 버튼을 눌러서 추가 텍스트를 볼 수 있도록 하는 기능을 구현해야겠다는 생각이 들었다.
let descriptionLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 7
label.lineBreakMode = .byTruncatingTail
이때, UILabel
에 numberOfLines
를 이용해 처음에는 텍스트가 7줄까지만 보이도록 설정하고,
버튼을 눌렀을 때 나머지 텍스트가 펼쳐지는 방식으로 진행하면 될 것 같아서 지정을 해두고,
label.lineBreakMode = .byTruncatingTail
를 속성을 작성했는데,
이건 UILabel의 텍스트가 길어질 때, 화면에 표시할 수 없을 경우 텍스트 끝에 어떻게 처리할지를 지정하는 속성이다.
이 속성의 값이 여러개 있었는데 그 중 하나인 .byTruncatingTail
은 텍스트가 UILabel
의 너비를 초과하게 되면
텍스트 끝에 "…"
이런식으로 생략 부호를 표시해 자르는 역할을 한다.
대충 텍스트 길이)
스크롤 되는지도 확인해야하고 길어야하기에 진격의 거인 소개글을 가져왔다.
그리고 이걸 쓰면서 알게 됐는데 Swift에서 문자열을 여러 줄로 작성할 때 사용하는 방법으로
"""
이 구문은 멀티라인 문자열 리터럴(Multi-line String Literal)을 나타낸다.
여러 줄에 걸쳐 있는 긴 텍스트를 하나의 문자열로 선언할 수 있게 해주는 편한 친구다.
더보기 토글버튼까지 UI 작업을 해서 줄거리 소개 view
아래에 잘 넣어주니 확인이 된다.
.
.
.
그렇게 구글에 폭풍 검색을 시작했다.
텍스트뷰 접었다 펴기,
텍스트뷰 더보기,
더보기 기능 이런식으로 검색을 했는데
블로그들을 보니 다들 저 isExpanded
라는걸 사용하는걸 발견했고
열기 닫기 설정이면 접었다 펴는 것에 대한 bool
타입이니 토글과 세트로 사용하는 걸 알게 됐다. -> isExpanded 공식문서
초기 상태에는 isExpanded = false
로 되어 있으니 텍스트는 7줄
로 제한되고,
버튼을 클릭하면 isExpanded
값이 true
로 변경되면 텍스트가 확장되어 모든 내용을 볼수있게 된다.
이 코드를 토글과 같이 사용하면 될 것 같았다.
// 더보기, 접기 동작 메서드
@objc private func toggleText() {
isExpanded.toggle()
if isExpanded {
descriptionLabel.numberOfLines = 0
toggleButton.setTitle("접기", for: .normal)
} else {
descriptionLabel.numberOfLines = 7
toggleButton.setTitle("더보기", for: .normal)
}
toggle() 공식문서를 보면 Bool 타입으로 되어있는데
toggleText()
메서드가 호출될 때마다 isExpanded
가 반전되면서 텍스트를 확장하거나 축소하는 동작을 하게 된다.
이때 아까 지정한 isExpanded
의 초기 값이 없다면 버튼을 클릭했을 때
첫 동작이 어떻게 될지 알 수 없기 때문에 isExpanded로 초기 상태를 명확히 설정해주는 것이 중요하다는 걸 알게됐다.
그리고 toggle()
메서드는 isExpanded
의 값을 반전시켜준다. ( true일 경우 false로, false일 경우 true로 바뀜 )
버튼을 클릭할 때마다 텍스트의 상태가 바뀌도록 하기 위해서 토글을 이용했고,
if문을 이용한 조건문을 통해 isExpanded
값에 따라 descriptionLabel.numberOfLines
가 조정될 수 잇게 하면 된다.
true
라면 텍스트가 확장되어 모든 텍스트가 보이도록 numberOfLines
를 0
으로 설정하고,
false
라면 텍스트가 축소돼서 7줄까지만 보이도록 numberOfLines
를 7
로 설정하게 된다.
그래 어쩐지 쉽게 됐었다.
문제가 생겼는데, "더보기"
버튼을 눌러서 텍스트를 확장시키고 텍스트가 화면을 넘을 정도로 길어졌을 때 스크롤로 아래 내용까지 확인해야 하는데 현재 스크롤이 되지 않는 점을 발견했다.
스크롤이 되지 않으면 사용자가 화면을 넘어서 소개 내용을 확인할 수 없기 때문에 이 문제를 해결하는 데 집중했다.
그렇게 혼자 1시간 동안 뷰 안에 스크롤 뷰를 넣어야하나 어떻게 해야하나 알아보고 있는 와중
팀원이 그 소개 뷰가 UIView
가 아닌 UIScrollView
로 해보라는 말에 진행해보게 됐다.
처음에는 UIScrollView
를 사용해야 한다는 점을 인지하지 못했다가 가만히 생각해보니..
스크롤이 안 된 이유는 UIScrollView
를 사용하지 않고 UILabel
만을 화면에 배치했기 때문이어서 그런걸까?
UILabel
은 기본적으로 스크롤 기능을 지원하지 않으니 내용이 많아지면 화면을 넘쳐서 보이지 않게 되니,
이때 스크롤을 구현하려면 UIScrollView
를 사용해서 내용이 스크롤될 수 있도록 해야 한다는 것을 깨달았다.
class MovieDescriptionView: UIScrollView {
let contentView = UIView()
이 문제를 해결하기 위해 UIScrollView
를 부모 뷰로 설정하고, 그 안에 텍스트를 담고 있는 UIView
를 추가하는 방식으로 접근했다.
UIScrollView
는 자식 뷰가 화면을 넘어서면 스크롤을 가능하게 해주는 뷰이기 때문에,
이 안에 텍스트가 담긴 UIView
를 넣고, UIScrollView
의 크기에 맞게 자식 뷰의 크기를 조정해주면 자연스럽게 스크롤이 될 수 있다.
그리고 UIView
타입으로 만든 프로퍼티인 contentView
의 오토레이아웃을 설정해주었다.
.
.
// 토클 클릭시 스크롤뷰 컨텐츠 크기 즉시 갱신
setNeedsLayout()
layoutIfNeeded()
그리고 더보기로 인해서 레이아웃이 바뀌다보니 이걸 갱신해주고 바로 반영해주는
setNeedsLayout()
과 layoutIfNeeded()
가 필요하다고 생각해서 코드 마지막 부분에 작성을 했는데,
테스트 해보니..UIScrollView
를 적용한 후에는 스크롤이 이미 너무 잘 되어서 ...
이 메서드들 없이도 레이아웃이 자연스럽게 갱신이 됐다. ^^
그럼에도 불구하고 혹시 모를 스크롤 뷰의 크기나 배치가 제대로 업데이트 되도록 하기 위해서
그냥 이 두 메서드를 추가적으로 넣는 걸 선택했다.
스크롤바 숨기는 기능은 검색하니 바로 나와서 알 수 있었다.
이 속성은 불타입이고 기본값이 true
로 되어있어서 false
로 해주어여 세로 스크롤이 없어진다고 하는데,
사용하려면 스크롤뷰를 초기화 하는 시점에 설정하면 된다고 해서 바로 지정후 사용해봤다.
showsVerticalScrollIndicator
만세!!!!!
결국, 오늘의 문제는 UIScrollView
를 활용해서 해결할 수 있었다.
하면서 조금이나마 스크롤 뷰를 이해하고 적용하는 방법을 배울 수 있었고, "더보기" 버튼 기능을 구현하면서 내가 이걸 만들 수 있을까 싶었지만 해내서 너무 뿌듯했다..
그리고 생각보다 swift의 기능적인 부분은 우리나라 블로그에 많이 없어서 아쉬웠는데 그 부분을 이렇게 내가 기록하며 채워가고 다른 사람에게도 도움이 되었으면 좋겠다고 생각하니 기분좋게 글을 쓴 것 같다.
계속해서 새롭게 알게 된 속성들을 적용해보는 것도 꽤나 재미있고 기쁘다.
상세페이지 맡으셨나요 손겸님..?