当 UITextView 的文本超出 1 行时展开 UITextView 和 UITableView
Posted
技术标签:
【中文标题】当 UITextView 的文本超出 1 行时展开 UITextView 和 UITableView【英文标题】:Expand UITextView and UITableView When UITextView's Text Extends Beyond 1 Line 【发布时间】:2016-05-03 21:45:38 【问题描述】:我有一个 UITableView,每个单元格内并排有两个 UITextView。我希望 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 的高度。
任何想法为什么会发生这种情况以及如何正确动态地更改 UITextView 和 UITableView 的高度?
【问题讨论】:
【参考方案1】:我的回答是基于我们在生产社交应用 Impether 时使用的确切内容,因为您在 Twitter 上问我您使用了该应用,并且您看到那里扩展了 UITextView。
首先,我们有一个自定义的基于UITableViewCell 的类,其中包含UITextView
,它将被扩展(这个类也有一个相应的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)
【讨论】:
感谢您的回答!我似乎无法让它工作我有两个并排的文本视图。两者都没有设置高度约束,但有一个宽度约束。我尝试启用滚动,但单元格仍然没有扩展,textView 只是被向上推以适应新行。有什么想法吗? 救了我该死的一天!【参考方案2】:首先确保您的自动布局约束与您设置的框架不冲突。 (如果一切正常但仍然无法正常工作)然后尝试将frame
更改为bounds
。视图的框架(CGRect)是其矩形在父视图坐标系中的位置。根据我的经验,使用frame
有时可能会导致奇怪的问题。
func textViewDidChange(textView: UITextView)
var frame : CGRect = textView.bounds
frame.size.height = textView.contentSize.height
textView.bounds = frame
【讨论】:
我仍然遇到同样的问题。我的 textView 是并排的,没有设置高度约束。我应该在我的自定义单元格类中调用 textViewDidChange 并且我的 tableVC 中的自动行高可以吗?以上是关于当 UITextView 的文本超出 1 行时展开 UITextView 和 UITableView的主要内容,如果未能解决你的问题,请参考以下文章
当 UITextView 大小发生变化时,如何调整 UITableViewCell 的大小?
当新行添加到 UITextView 实例中时,如何向上滚动视图?