How to Implement UITextView inside UITableView inside UITableView Swift

前端 未结 2 1819
青春惊慌失措
青春惊慌失措 2021-01-29 04:10

how to implement UITextView inside UITableView inside UITableView ??

(1) If you type text in \'UITextView\', the height of \'UITableViewCell2\' is automatically

相关标签:
2条回答
  • 2021-01-29 04:40

    Nesting table views may not be the ideal solution for this, but your UITableViewCell would need to estimate and measure the whole height of the embedded UITableView, and propagate changes up to the parent table.

    0 讨论(0)
  • 2021-01-29 04:52

    You might want to give this a try...

    It using a single-section table view. Each cell contains a UIStackView that arranges the (variable) UITextViews.

    No @IBOutlet or @IBAction or prototype cell connections... just assign a standard UIViewController custom class to TableTextViewsViewController:

    //
    //  TableTextViewsViewController.swift
    //  Created by Don Mag on 3/10/20.
    //
    
    import UIKit
    
    class TextViewsCell: UITableViewCell, UITextViewDelegate {
    
        let frameView: UIView = {
            let v = UIView()
            v.backgroundColor = .clear
    
            v.layer.borderColor = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0).cgColor
            v.layer.borderWidth = 1
    
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        let stackView: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.spacing = 8
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        let stackViewPadding: CGFloat = 8.0
    
        var textViewCosure: ((Int, String)->())?
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            commonInit()
        }
    
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
    
        func commonInit() -> Void {
    
            let g = contentView.layoutMarginsGuide
    
            contentView.addSubview(frameView)
            frameView.addSubview(stackView)
    
            // bottom constraint needs to be less than 1000 (required) to avoid auot-layout warnings
            let frameViewBottomConstrait = frameView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0)
            frameViewBottomConstrait.priority = UILayoutPriority(rawValue: 999)
    
            NSLayoutConstraint.activate([
    
                frameView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
                frameView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
                frameView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
                frameViewBottomConstrait,
    
                stackView.topAnchor.constraint(equalTo: frameView.topAnchor, constant: stackViewPadding),
                stackView.leadingAnchor.constraint(equalTo: frameView.leadingAnchor, constant: stackViewPadding),
                stackView.trailingAnchor.constraint(equalTo: frameView.trailingAnchor, constant: -stackViewPadding),
                stackView.bottomAnchor.constraint(equalTo: frameView.bottomAnchor, constant: -stackViewPadding),
    
            ])
    
        }
    
        override func prepareForReuse() {
            super.prepareForReuse()
            stackView.arrangedSubviews.forEach {
                $0.removeFromSuperview()
            }
        }
    
        func fillData(_ strings: [String]) -> Void {
            strings.forEach {
                let v = UITextView()
    
                v.font = UIFont.systemFont(ofSize: 16.0)
                v.isScrollEnabled = false
    
                // hugging and compression resistance set to required for cell expansion animation
                v.setContentHuggingPriority(.required, for: .vertical)
                v.setContentCompressionResistancePriority(.required, for: .vertical)
    
                v.text = $0
    
                // frame the text view
                v.layer.borderColor = UIColor.blue.cgColor
                v.layer.borderWidth = 1
    
                v.delegate = self
                stackView.addArrangedSubview(v)
            }
        }
    
        func textViewDidChange(_ textView: UITextView) {
            guard let idx = stackView.arrangedSubviews.firstIndex(of: textView) else {
                fatalError("Shouldn't happen, but couldn't find the textView index")
            }
            textViewCosure?(idx, textView.text)
        }
    
    }
    
    class TableTextViewsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
        let topLabel: UILabel = {
            let v = UILabel()
            v.text = "Top Label"
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        let tableView: UITableView = {
            let v = UITableView()
    
            v.layer.borderColor = UIColor.red.cgColor
            v.layer.borderWidth = 1
    
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        var myData: [[String]] = [[String]]()
        var textViewsInRows: [Int] = [
            3, 4, 2, 6, 1, 4, 3,
        ]
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // generate some dummy data
            var i = 1
            textViewsInRows.forEach {
                var s: [String] = [String]()
                for j in 1...$0 {
                    s.append("Table Row: \(i) TextView \(j)")
                }
                myData.append(s)
                i += 1
            }
    
            view.addSubview(topLabel)
            view.addSubview(tableView)
    
            let g = view.safeAreaLayoutGuide
    
            NSLayoutConstraint.activate([
    
                topLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
                topLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
                topLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
    
                tableView.topAnchor.constraint(equalTo: topLabel.bottomAnchor, constant: 8.0),
                tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
                tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
                tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
    
            ])
    
            tableView.dataSource = self
            tableView.delegate = self
    
            tableView.separatorStyle = .none
            tableView.keyboardDismissMode = .onDrag
    
            tableView.register(TextViewsCell.self, forCellReuseIdentifier: "TextViewsCell")
    
        }
    
        // MARK: - Table view data source
    
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return myData.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "TextViewsCell", for: indexPath) as! TextViewsCell
    
            cell.fillData(myData[indexPath.row])
    
            cell.textViewCosure = { [weak self] idx, str in
                // update our data
                self?.myData[indexPath.row][idx] = str
                // update table view cell height
                self?.tableView.beginUpdates()
                self?.tableView.endUpdates()
            }
    
            return cell
        }
    
    }
    

    Result - red border is the tableView, green border is each cell's contentView, blue border is each textView:

    0 讨论(0)
提交回复
热议问题