簡體   English   中英

當UITextView的文本超出1行時,展開UITextView和UITableView

[英]Expand UITextView and UITableView When UITextView's Text Extends Beyond 1 Line

我有一個UITableView,每個單元格內有兩個UITextViews。 我希望UITableViewCell和UITextView的高度都增加,這樣用戶就不需要在UITextView中滾動了。 這是我嘗試過的:

在TableViewController類中:

    self.tableView.estimatedRowHeight = 44
    self.tableView.rowHeight = UITableViewAutomaticDimension

在TableViewCell類中(從這里得到):

func textViewDidChange(textView: UITextView) {

    var frame : CGRect = textView.frame
    frame.size.height = textView.contentSize.height
    textView.frame = frame
}

當用戶輸入超出UITextView的設置寬度時,UITableView將高度從44增加到大約100,UITextView的高度不會增加。 我設置了約束,以便UITextView的高度等於UITableViewCell的高度。

任何想法為什么會發生這種情況以及如何正確地動態更改UITextView和UITableView的高度?

我的答案是基於我們在社交應用程序Impether的制作中使用的內容 ,因為您在Twitter上詢問我使用了該應用程序並且您看到了在那里擴展UITextView。

首先,我們有一個包含UITextView的自定義UITableViewCell類,它將被展開(該類還有一個相應的xib文件,你可以自己設計):

class MultiLineTextInputTableViewCell: UITableViewCell {

    //our cell has also a title, but you
    //can get rid of it
    @IBOutlet weak var titleLabel: UILabel!
    //UITextView we want to expand
    @IBOutlet weak var textView: UITextView!

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    /// Custom setter so we can initialize the height of the text view
    var textString: String {
        get {
            return textView?.text ?? ""
        }
        set {
            if let textView = textView {
                textView.text = newValue
                textView.delegate?.textViewDidChange?(textView)
            }
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()        
        // Disable scrolling inside the text view so we enlarge to fitted size
        textView?.scrollEnabled = false        
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        if selected {
            textView?.becomeFirstResponder()
        } else {
            textView?.resignFirstResponder()
        }
    }
}

定義了自定義單元格,您可以在基於UITableViewController的類中使用它,如下所示:

class YourTableViewController: UITableViewController {

    //in case where you want to have
    //multiple expanding text views
    var activeTextView: UITextView?

    override func viewDidLoad() {
        super.viewDidLoad()

        //registering nib for a cell to reuse
        tableView.registerNib(
            UINib(nibName: "MultiLineTextInputTableViewCell", bundle: nil),
            forCellReuseIdentifier: "MultiLineTextInputTableViewCell")

    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        //hide keyboard when view controller disappeared
        if let textView = activeTextView {
            textView.resignFirstResponder()
        }
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        //put your value here
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //put your value here
        return 2
    }

    override func tableView(tableView: UITableView,
                            cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let row = indexPath.row
        let cell = tableView.dequeueReusableCellWithIdentifier(
            "MultiLineTextInputTableViewCell",
            forIndexPath: indexPath) as! MultiLineTextInputTableViewCell

        let titleText = "Title label for your cell"
        let textValue = "Text value you want for your text view"

        cell.titleLabel.text = titleText
        cell.textView.text = textValue

        //store row of a cell as a tag, so you can know
        //which row to reload when the text view is expanded
        cell.textView.tag = row
        cell.textView.delegate = self

        return cell

    }

    override func tableView(tableView: UITableView,
                            estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        //standard row height
        return 44.0
    }

    override func tableView(tableView: UITableView,
                            heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }

    // Override to support conditional editing of the table view.
    override func tableView(tableView: UITableView,
                            canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }
}

//extension containing method responsible for expanding text view
extension YourTableViewController: UITextViewDelegate {

    func textViewDidEndEditing(textView: UITextView) {
        let value = textView.text
        //you can do something here when editing is ended
    }

    func textView(textView: UITextView, shouldChangeTextInRange range: NSRange,
                  replacementText text: String) -> Bool {
        //if you hit "Enter" you resign first responder
        //and don't put this character into text view text
        if text == "\n" {
            textView.resignFirstResponder()
            return false
        }
        return true
    }

    func textViewDidBeginEditing(textView: UITextView) {
        activeTextView = textView
    }

    //this actually resize a text view
    func textViewDidChange(textView: UITextView) {

        let size = textView.bounds.size
        let newSize = textView.sizeThatFits(CGSize(width: size.width,
            height: CGFloat.max))

        // Resize the cell only when cell's size is changed
        if size.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            tableView?.beginUpdates()
            tableView?.endUpdates()
            UIView.setAnimationsEnabled(true)

            let thisIndexPath = NSIndexPath(forRow: textView.tag, inSection: 0)
            tableView?.scrollToRowAtIndexPath(thisIndexPath,
                                              atScrollPosition: .Bottom,
                                              animated: false)
        }
    }
} 

首先確保您的自動布局約束不與您設置的幀沖突。 (如果一切正常但仍然不起作用)然后嘗試將frame更改為bounds 視圖的框架(CGRect)是其超視圖坐標系中矩形的位置。 在我的經驗中,使用frame可能會導致奇怪的問題。

func textViewDidChange(textView: UITextView) {

    var frame : CGRect = textView.bounds
    frame.size.height = textView.contentSize.height
    textView.bounds = frame
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM