• TextView 를 UIView 위에 올려 버튼, ScrollView등 다양한 UI 작업
func textViewDidChange(_ textView: UITextView) {
let lineHeight = textView.font?.lineHeight ?? 0
let maxHeight = lineHeight * 3 + textView.textContainerInset.top + textView.textContainerInset.bottom
let width = textView.bounds.width > 0 ? textView.bounds.width : UIScreen.main.bounds.width - 50
let estimatedSize = textView.sizeThatFits(CGSize(width: width, height: .infinity))
let finalHeight = min(estimatedSize.height, maxHeight)
textView.isScrollEnabled = estimatedSize.height > maxHeight
textViewHeightConstraint?.update(offset: finalHeight)
let topPadding: CGFloat = 10
let bottomPadding: CGFloat = 10
let contentHeight = max(finalHeight, 21)
let totalHeight = topPadding + contentHeight + bottomPadding
onHeightChange?(totalHeight)
UIView.animate(withDuration: 0.1) {
self.superview?.layoutIfNeeded()
}
}
textView 안에서 글을 입력하게 되면, 해당 글씨의 lineHeight를 계산해 3줄까지를 maxHeight 값으로 기준을 잡고, 그 기준을 넘지 않았을떄(1줄 또는 2줄일때) 는 계산된 height에 따라 onHeightChange 클로져를 통해 CustomTextView의 높이를 바꿔주고, maxHeight에 도달했을때는 더이상 변화되지 않고, textView가 scroll 되게 구성해주었습니다.
func movePlusButtonToBottom(_ move: Bool) {
plusButtonTopConstraint?.deactivate()
plusButton.snp.makeConstraints {
if move {
plusButtonTopConstraint = $0.top.equalTo(tagScrollView.snp.top).offset(6).constraint
tagScrollView.isHidden = false
tagStackView.isHidden = false
} else {
plusButtonTopConstraint = $0.top.equalToSuperview().offset(10).constraint
tagScrollView.isHidden = true
tagStackView.isHidden = true
}
}
UIView.animate(withDuration: 0.3) {
self.layoutIfNeeded()
}
}
이 함수는 plusButton이 keyboard가 올라가고 내려갈때 레이아웃을 바꿔주기위해 만들어준 함수입니다. 여기서 move의 매개변수는,
keyboard observer 가 동작할때 받습니다.
만약 keyboard가 올라오지 않는 상태라면, textView의 top에 10으로 고정시켜두었다가, keyboard가 동작하면 하단에 있던 tagScrollView 의 top으로 constraint 를 옮겨지도록 위치를 조정해 주었습니다.
func addTag(title: String) {
let tagView = TagListView(title: title)
tagView.onTap = { [weak self, weak tagView] in
guard let self, let tagView else { return }
self.tagStackView.removeArrangedSubview(tagView)
tagView.removeFromSuperview()
self.updateTagVisibility()
}
tagStackView.addArrangedSubview(tagView)
updateTagVisibility()
}
private func updateTagVisibility() {
tagScrollView.isHidden = tagStackView.arrangedSubviews.isEmpty
}
addTag 함수는, customTextView 하단에 해쉬태그 버튼들을 달아주기 위한 함수입니다.
미리 객체로 만들어둔 TagListView에 onTap 클로져를 통해 각 버튼 하나하나의 동작을 할당해주는 함수로, VC에서 각 버튼 개수만큼 추가를 해주면 되도록 만들었습니다.
vc 에서 textView.addTag("Swift") 를 하면 Swift 태그 버튼이 ScrollView의 stackView 안에 포함이 되며, 여러번 사용하면, 각 버튼들이 순서대로 스택뷰에 담기도록 구현해주었습니다.
이때 만들어지는 과정을 살펴보면,