首页 文章

当UITextView的文本超出1行时,展开UITextView和UITableView

提问于
浏览
4

我有一个UITableView,每个单元格内有两个UITextViews . 我希望UITableViewCell和UITextView的高度都增加,这样用户就不需要在UITextView中滚动了 . 这是我尝试过的:

在TableViewController类中:

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

在TableViewCell类中(从here获取):

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的高度 .

任何想法为什么会发生这种情况和 how to correctly dynamically change the UITextView and UITableView's heights?

2 回答

  • 1

    我的回答是基于我们在社交应用程序生成中使用的内容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)
            }
        }
    }
    
  • 8

    首先确保您的自动布局约束不起作用)然后尝试将 frame 更改为 bounds . 一个视图's frame (CGRect) is the position of its rectangle in the superview'的坐标系 . 在我的经验中,使用 frame 可能会导致奇怪的问题 .

    func textViewDidChange(textView: UITextView) {
    
        var frame : CGRect = textView.bounds
        frame.size.height = textView.contentSize.height
        textView.bounds = frame
    }
    

相关问题