강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

듀듀님의 프로필 이미지
듀듀

작성한 질문수

스위프트, UIKit 에서 테이블 뷰 내 텍스트뷰 높이 조절

작성

·

48

0

image.png

지금 당근마켓의 내물건 팔기를 구현하고 있습니다.

 

전체적으로 UITableView로 만들고 각 셀마다 맞는 셀을 구현했습니다.

 

텍스트 뷰에 글을 작성하면 텍스트뷰의 높이가 글자 수에 맞춰 늘어나는데, 이때 키보드는 화면 하단에 고정되어 있는것으로 판단됩니다.

 

그래서 아래와 같이 구현해봤습니다.

class FeedViewController: UIViewController {
    
    // MARK: - Variable
    private let tableSection: [String] = ["이미지", "제목", "내용"]
    var selectedImages: [UIImage] = []
    
    
    // MARK: - UI Components
    
    private let feedTableView: UITableView = {
        let tableView = UITableView(frame: .zero, style: .insetGrouped)
        tableView.separatorStyle = .none
        tableView.showsVerticalScrollIndicator = false
        tableView.alwaysBounceVertical = false
        tableView.isScrollEnabled = true
        return tableView
    }()

...

// MARK: - Layout
    private var feedTableViewBottomConstraint: NSLayoutConstraint!
    private var registerButtonTopConstraint: NSLayoutConstraint!

    private func configureConstraints() {
        view.addSubview(feedTableView)
        view.addSubview(registerFeedButton)
        
        feedTableView.translatesAutoresizingMaskIntoConstraints = false
        registerFeedButton.translatesAutoresizingMaskIntoConstraints = false
        
        // 제약 조건 저장
        feedTableViewBottomConstraint = feedTableView.bottomAnchor.constraint(equalTo: registerFeedButton.topAnchor, constant: -10)
        registerButtonTopConstraint = registerFeedButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10)
        
        NSLayoutConstraint.activate([
            
            // 테이블뷰 제약조건
            feedTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            feedTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            feedTableView.topAnchor.constraint(equalTo: view.topAnchor),
            feedTableViewBottomConstraint,
            
            // 버튼 제약조건
            registerFeedButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
            registerFeedButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15),
            registerFeedButton.heightAnchor.constraint(equalToConstant: 50),
            registerButtonTopConstraint
        ])
        
        // 키보드 노티피케이션 설정
        setupKeyboardNotifications()
    }
    

    private func setupKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc private func keyboardWillShow(_ notification: Notification) {
        if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
            // 키보드가 올라오면 테이블뷰의 bottom을 키보드의 top에 맞춤
            feedTableViewBottomConstraint.constant = -keyboardFrame.height + 100

            UIView.animate(withDuration: 0.3) {
                self.view.layoutIfNeeded()
            }
        }
    }

    @objc private func keyboardWillHide(_ notification: Notification) {
        // 키보드가 내려가면 테이블뷰의 bottom을 버튼의 top으로 복원
        feedTableViewBottomConstraint.constant = -10
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }
    }

 

그리고 ContentInputCell 이라고해서 텍스트뷰를 입력하는 곳에는 아래와 같이 작성했습니다.

    // MARK: - UI Component
    private let contentTextView: UITextView = {
        let textView = UITextView()
        textView.text = "오늘 하루는 어땠나요? 😀"
        textView.backgroundColor = .systemBackground
        textView.layer.cornerRadius = 5
        textView.layer.masksToBounds = true
        
        // 글자 수에 따라 크기가 늘어가게 하기 위함
        textView.isScrollEnabled = false

        textView.textAlignment = .left
        textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        textView.textColor = .secondaryLabel
        textView.backgroundColor = .systemBackground
        textView.font = UIFont.systemFont(ofSize: 16, weight: .bold)
        return textView
    }()
...

 private func configureConstraints() {
        contentView.addSubview(contentTextView)
        
        contentTextView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            
            contentTextView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            contentTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            contentTextView.topAnchor.constraint(equalTo: contentView.topAnchor),
            contentTextView.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor, constant: 5),
            contentTextView.heightAnchor.constraint(greaterThanOrEqualToConstant: 350)
            
        ])
    }

// MARK: - Extension: UITextViewDelegate
extension ContentInputCell: UITextViewDelegate {
    
    func textViewDidChange(_ textView: UITextView) {
        guard let tableView = tableView else { return }

        let contentSize = textView.sizeThatFits(CGSize(width: textView.bounds.width, height: .infinity))

        if textView.bounds.height != contentSize.height {
            tableView.contentOffset.y += contentSize.height - textView.bounds.height

            UIView.setAnimationsEnabled(false)
            tableView.beginUpdates()
            tableView.endUpdates()
            UIView.setAnimationsEnabled(true)
        }
    }
}

extension ContentInputCell {

    var tableView: UITableView? {
        var view = superview
        while view != nil && !(view is UITableView) {
            view = view?.superview
        }

        return view as? UITableView
    }
}

답변 1

0

안녕하세요, 인프런 AI 인턴입니다. 듀듀님.

스위프트와 UIKit에서 텍스트뷰의 높이를 동적으로 조절하는 방법에 대해 고민하고 계신 것 같아요. 문제를 해결하기 위해 몇 가지 사항을 확인해보시는 것을 추천드립니다.

  1. UITextView의 높이 업데이트:

    • textViewDidChange 메서드 내에서 contentSize.height를 사용해 텍스트뷰의 높이를 측정하고 셀의 높이를 업데이트하도록 구현하고 계시네요. 이 방법은 옳습니다. 그러나 textViewDidChange 메소드 안에서 tableView.contentOffset.y를 조정하는 부분은 높이 변화에 따른 스크롤 위치 조정을 위함이라면, 불필요할 수 있습니다. UITableView의 beginUpdates() / endUpdates() 호출만으로도 셀의 높이 변화에 따라 테이블뷰가 자연스럽게 조정될 수 있습니다.
  2. Auto Layout Constraints:

    • Constraints에서 contentTextView.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor, constant: 5)를 사용하는데, keyboardLayoutGuide는 보통 키보드와의 위치를 조정할 때 사용되며 여기서는 필요하지 않을 수 있습니다. 대신 contentTextView의 높이를 UITextViewDelegate 메서드에서 동적으로 업데이트하도록 조정해보세요.
  3. 키보드와의 상호작용:

    • 키보드가 나타남에 따라 뷰가 잘못된 위치나 크기로 나타날 수 있는데, keyboardWillShowkeyboardWillHide 메서드에서 테이블뷰의 bottomConstraint를 올바르게 조정하고 계신 것 같습니다.

이미 많은 부분을 잘 구현하셨으니, 위의 내용을 바탕으로 문제를 한 번 더 검토해보시기 바랍니다. 추가적으로 수정 또는 개선해야 할 부분이 있을 경우 말씀해 주세요.

도움이 되었기를 바랍니다! 😊

image description

듀듀님의 프로필 이미지
듀듀

작성한 질문수

질문하기