๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS/UI

[iOS/UI] ํ…Œ์ด๋ธ”๋ทฐ ์•ˆ์— ์žˆ๋Š” ํ…์ŠคํŠธ๋ทฐ ๋†’์ด ๊ธ€์— ๋”ฐ๋ผ ์กฐ์ •ํ•˜๊ธฐ(Dynamic tableviewcell height by textview text)

by Fomagran ๐Ÿ’ป 2021. 3. 30.
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma ์ž…๋‹ˆ๋‹ค!

 

์˜ค๋Š˜์€ ์•Œ์•„๋ณผ๊ฑด ํ…์ŠคํŠธ๋ทฐ์•ˆ์— ๊ธ€์”จ์— ๋”ฐ๋ผ์„œ ํ…Œ์ด๋ธ”๋ทฐ์…€์˜ ๋†’์ด๊ฐ€ ์ž๋™์œผ๋กœ ์กฐ์ •๋˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณผ๊ฑฐ์—์š”!

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


Storyboard

 

์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ํ…Œ์ด๋ธ”๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์‹œ๊ณ 

 

ํ…Œ์ด๋ธ”๋ทฐ์…€ ์•ˆ์— ํ…์ŠคํŠธ๋ทฐ๋ฅผ ๋„ฃ์–ด์ฃผ์„ธ์š”!

 

(ํ…์ŠคํŠธ๋ทฐ๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๊ฑธ ํ•œ ๋ˆˆ์œผ๋กœ ๋ณด๊ธฐ ์œ„ํ•ด ํ…Œ์ด๋ธ”๋ทฐ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒ‰์„ ๊ฒ€์ •์ƒ‰์œผ๋กœ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.)

 

์˜คํ† ๋ ˆ์ด์•„์›ƒ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด์ฃผ์„ธ์š”!


TableViewCell

 

ํ…Œ์ด๋ธ”๋ทฐ์— ํ…์ŠคํŠธ๋ทฐ๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ์„ธ์š”!

class TableViewCell: UITableViewCell {

    @IBOutlet weak var textView: UITextView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

}

๋จผ์ € ํ…์ŠคํŠธ๋ทฐ์— ๋”ฐ๋ผ ํ…Œ์ด๋ธ”๋ทฐ์…€์˜ ๋†’์ด๊ฐ€ ๋ฐ”๋€Œ๊ฒŒ ํ•  ํ”„๋กœํ† ์ฝœ์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

protocol TableViewCellDelegate:class {
    func updateTextViewHeight(_ cell:ApplyTableViewCell,_ textView:UITextView)
}

๋”œ๋ฆฌ๊ฒŒ์ดํŠธ๋„ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”.

weak var delegate: TableViewCellDelegate?

 

์•„๋ž˜์™€ ๊ฐ™์ด ํ…์ŠคํŠธ๋ทฐ ์„ธํŒ…์„ ํ•ด์ฃผ๊ณ  awakeFromNib() ๋ฐ‘์— ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผœ์ฃผ์„ธ์š”.

  func setTextView() {
        textView.delegate = self
        textView.isScrollEnabled = false
        textView.sizeToFit()
    }

 

ํ…Œ์ด๋ธ”๋ทฐ์…€ ๋ฐ‘์— UITextViewDelegate๋ฅผ ์ฑ„ํƒํ•ด์ฃผ์‹œ๊ณ  

 

ํ…์ŠคํŠธ๋ทฐ์˜ ๊ธ€์”จ๊ฐ€ ๋ฐ”๋€”๋•Œ๋งˆ๋‹ค ํ”„๋กœํ† ์ฝœ์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ”๋€Œ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

//MARK:UITextViewDelegate

extension ApplyTableViewCell:UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        if let delegate = delegate {
            delegate.updateTextViewHeight(self, textView)
        }
    }
    
}

TableViewController

 

๋จผ์ € ํ…Œ์ด๋ธ”๋ทฐ ์…€์˜ ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ํ˜„์žฌ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.

   override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
        cell.delegate = self
        return cell
    }

ํ…Œ์ด๋ธ”๋ทฐ์˜ ํ–‰ ๋†’์ด๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด UItableView.automaticDimension์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.

 

(์•Œ์•„์„œ ํ–‰๋†’์ด ๋งž์ถฐ์ค˜์™€ ๊ฐ™์€๊ฑด๋ฐ ์ •๋ง ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค!)

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

๊ทธ๋ฆฌ๊ณค ๋‹ค์Œ๊ณผ ๊ฐ™์ด TableViewCellDelegate๋ฅผ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.

 

๊ฐ„๋‹จํžˆ ์„ค๋ช…๋“œ๋ฆฌ๋ฉด ํ…์ŠคํŠธ๋ทฐ๊ฐ€ ๋ฐ”๋€”๋•Œ๋งˆ๋‹ค ํ…Œ์ด๋ธ”๋ทฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

extension TableViewController:TableViewCellDelegate {
    func updateTextViewHeight(_ cell: TableViewCell, _ textView: UITextView) {
        let size = textView.bounds.size
        let newSize = tableView.sizeThatFits(CGSize(width: size.width,
                                                    height: CGFloat.greatestFiniteMagnitude))
        if size.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            tableView.beginUpdates()
            tableView.endUpdates()
            UIView.setAnimationsEnabled(true)
        }
    }
}

์•„๋ž˜๋Š” ์‹คํ–‰ํ–ˆ์„ ๋•Œ ํ™”๋ฉด์ž…๋‹ˆ๋‹ค!


 

์œ„์— ํ™”๋ฉด์„ ๋ณด๋ฉด ๋งจ ์ฒ˜์Œ ํ…์ŠคํŠธ๋ทฐ๊ฐ€ ์‹คํ–‰๋ ๋•Œ ๋„ˆ๋ฌด ์ž‘๋‹ค๋Š” ๋Š๋‚Œ์„ ๋ฐ›์•˜์–ด์š”.

 

Storyboard

 

๊ทธ๋ž˜์„œ ์Šคํ† ๋ฆฌ๋ณด๋“œ์— ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ํ…์ŠคํŠธ๋ทฐ ์•„๋ž˜์—๋‹ค ์„ธํŒ…ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.


TableViewCell

 

์•„๋ž˜์™€ ๊ฐ™์ด View๋ฅผ ํ…Œ์ด๋ธ”๋ทฐ์…€์— ์—ฐ๊ฒฐํ•ด์ฃผ์‹œ๊ณ 

 @IBOutlet weak var emptyView: UIView!

emptyView์— ์ œ์Šค์ณ ๋ ˆ์ฝ”๊ทธ๋‚˜์ด์ €๋ฅผ ๋„ฃ์–ด์ฃผ์‹œ๊ณ .

 

๋ทฐ๋ฅผ ํƒญํ–ˆ์„๋•Œ ํ…์ŠคํŠธ๋ทฐ๊ฐ€ ์‹คํ–‰(?)๋˜๊ฒŒ ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

   func setEmptyView() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapEmptyView))
             emptyView.addGestureRecognizer(tap)
    }
    
    @objc func tapEmptyView() {
        textView.becomeFirstResponder()
    }

setEmptyView๋„ awakeFromNib()์—์„œ ์‹คํ–‰์‹œ์ผœ์ค๋‹ˆ๋‹ค.


emptyView๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹คํ–‰์‹œํ‚จ ํ™”๋ฉด

 


์˜ค๋Š˜์€ ์ด๋ ‡๊ฒŒ ํ…์ŠคํŠธ๋ทฐ์˜ ๊ธ€์”จ์— ๋”ฐ๋ผ์„œ ํ…Œ์ด๋ธ”๋ทฐ ์…€์˜ ๋†’์ด๊ฐ€ ๋™์ ์œผ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

ํ˜น์‹œ๋ผ๋„ ์ง€์ ํ•ด์ฃผ์‹ค ๋ถ€๋ถ„์ด๋‚˜ ํ‹€๋ฆฐ์ ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”!

 


Source Code

 

TableViewCell

protocol TableViewCellDelegate:class {
    func updateTextViewHeight(_ cell:TableViewCell,_ textView:UITextView)
}

class TableViewCell: UITableViewCell {
    
    weak var delegate: TableViewCellDelegate?

    @IBOutlet weak var emptyView: UIView!
    @IBOutlet weak var textView: UITextView!
    override func awakeFromNib() {
        super.awakeFromNib()
        setTextView()
        setEmptyView()
    }
    
    func setTextView() {
        textView.delegate = self
        textView.isScrollEnabled = false
        textView.sizeToFit()
    }
    
    func setEmptyView() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapEmptyView))
             emptyView.addGestureRecognizer(tap)
    }
    
    @objc func tapEmptyView() {
        textView.becomeFirstResponder()
    }

}

extension TableViewCell:UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        if let delegate = delegate {
            delegate.updateTextViewHeight(self, textView)
        }
    }
}

 

TableViewController

 

import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    // MARK: - Table view data source
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        
        return 1
    }
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return 1
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
        cell.delegate = self
        return cell
    }
    
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return UITableView.automaticDimension
    }
    

}

extension TableViewController:TableViewCellDelegate {
    func updateTextViewHeight(_ cell: TableViewCell, _ textView: UITextView) {
        let size = textView.bounds.size
        let newSize = tableView.sizeThatFits(CGSize(width: size.width,
                                                    height: CGFloat.greatestFiniteMagnitude))
        print(newSize)
        if size.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            tableView.beginUpdates()
            tableView.endUpdates()
            UIView.setAnimationsEnabled(true)
        }
    }
}

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€