How can I adjust the UITableViewCell height to the content of UITextView that's inside?
The key to getting self-sizing table cells (autolayout-based, which I recommend) is as follows:
- Add your subviews to the
contentView
of theUITableViewCell
- Provide constraints between your subviews and the
contentView
such that your subviews reach all edges of the table cell. In your case, this probably means aligning theleading
,trailing
,top
, andbottom
edges of yourUITextView
to the corresponding edges of thecontentView
. - Set the row height to
UITableViewAutomaticDimension
instead of a hardcodedCGFloat
. - Somewhere in your controller, provide an estimation of the height with
tableView.estimatedRowHeight = x
(a hard coded constant is fine, this is for performance).
Adjust height of UITableViewCell to height of UITextView
I think you need to use self-sizing UITableViewCell
. Replace your current implementation of heightForRowAt
with the following:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Now height of cells in your UITableView
object will be calculated automatically based on constraints.
Also, add some estimated value for row height:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100.0 // You can set any other value, it's up to you
}
Now you will see that the UITextView
view fills the whole UITableViewCell
cell.
Any way to dynamically adjust the height of a UITextView inside a UIStackView inside a UITableViewCell?
Turns out that just writing out that question in detail and then looking at a different question on StackOverflow allowed me to find one of several answers that described the solution to this predicament.
The answer:
func textViewDidChange(_ textView: UITextView) {
self.listTableView.beginUpdates()
self.listTableView.endUpdates()
}
Calling .beginUpdates()
and .endUpdates()
apparently calls the table view's delegate methods without breaking the editing process like .reloadData()
does, allowing for truly dynamic table row height changes while editing a text view inside the table row.
Resize UITableViewCell containing UITextView upon typing
Here is a swift solution that is working fine for me. Provided you are using auto layout, you need assign a value to estimatedRowHeight and then return UITableViewAutomaticDimension for the row height. Finally do something similar to below in the text view delegate.
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 44.0
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
// MARK: UITextViewDelegate
func textViewDidChange(textView: UITextView) {
// Calculate if the text view will change height, then only force
// the table to update if it does. Also disable animations to
// prevent "jankiness".
let startHeight = textView.frame.size.height
let calcHeight = textView.sizeThatFits(textView.frame.size).height //iOS 8+ only
if startHeight != calcHeight {
UIView.setAnimationsEnabled(false) // Disable animations
self.tableView.beginUpdates()
self.tableView.endUpdates()
// Might need to insert additional stuff here if scrolls
// table in an unexpected way. This scrolls to the bottom
// of the table. (Though you might need something more
// complicated if editing in the middle.)
let scrollTo = self.tableView.contentSize.height - self.tableView.frame.size.height
self.tableView.setContentOffset(CGPoint(x: 0, y: scrollTo), animated: false)
UIView.setAnimationsEnabled(true) // Re-enable animations.
}
How to set UITextView's height dynamically in UITableViewCell based on string size?
When using Auto-Layout for dynamically sizing cells, you don't really need to implement sizeThatFits(...)
. If the constraints are setup correctly, then you only need to disable the scrolling of the UITextView
.
From code:
yourTextView.scrollEnabled = false
From IB:
Select your Text View and open Attributes inspector, then
UITextView inside tableview not resizing according to content
I have tried with UITextView
inside UITableViewCell
.
Constraints
UITextView
, top, bottom and right as 2, 2 and 5, Width as 50. Font Size
as 13, Alignment
as Center. Give Outlet connection
for Width constraints
as txtVwWidthConst
UIViewController
@IBOutlet weak var tblView: UITableView!
var textWidthHeightDict = [Int : CGSize]()
override func viewDidAppear(_ animated: Bool) {
stringValue = [0 : "qwer\nasdasfasdf", 1 : "qwe", 2 : "123123\nasdas\nwqe", 3 : "q\n3\n4", 4 : "klsdfjlsdhfjkhdjkshfjadhskfjhdjksfhkdjsahfjksdhfkhsdfhjksdfjkasklsdfjlsdhfjkhdjkshfjadhskfjhdjksfhkdjsahfjksdhfkhsdfhjksdfjkasklsdfjlsdhfjkhdjkshfjadhskfjhdjksfhkdjsahfjksdhfkhsdfhjksdfjkas"]
for i in 0..<stringValue.count
{
GettingTextViewSize(getStr: stringValue[i]!, fontSize: 14, loopValue: i)
}
tblView.reloadData()
}
func GettingTextViewSize(getStr : String, fontSize: CGFloat, loopValue : Int)
{
var textSize = (getStr as! NSString).size(withAttributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: fontSize)])
if textSize.width > self.tblView.frame.width
{
// IF STRING WIDTH GREATER THAN TABLEVIEW WIDTH
let multipleValue = textSize.width / self.tblView.frame.width
textSize.height = (textSize.height * (multipleValue + 1.0))
textSize.width = self.tblView.frame.width
textWidthHeightDict[loopValue] = textSize
}
else
{
textSize.height = textSize.height + 10 //ADDING EXTRA SPACE
textSize.width = textSize.width + 10 //ADDING EXTRA SPACE
textWidthHeightDict[loopValue] = textSize
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stringValue.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "table", for: indexPath) as! TblTableViewCell
cell.backgroundColor = cellBGColr[indexPath.row]
cell.txtVw.inputAccessoryView = toolBar
cell.txtVw.text = stringValue[indexPath.row]
cell.txtVw.tag = indexPath.row
cell.txtVwWidthConst.constant = (textWidthHeightDict[indexPath.row]?.width)!
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var heightVal = (textWidthHeightDict[indexPath.row])
return heightVal!.height + 8 //ADDING EXTRA SPACE
}
UITableViewCell
class TblTableViewCell: UITableViewCell {
@IBOutlet weak var txtVw: UITextView!
@IBOutlet weak var txtVwWidthConst: NSLayoutConstraint!
// TEXTVIEW WIDTH CONSTRAINTS
override func awakeFromNib() {
super.awakeFromNib()
}
}
Output
Note
UITextView
only, we have to calculate String size. But, in UILabel
, this concept is very simple. Let me know, if you have any queries.
Related Topics
Circular Button Becomes Rounded Rectangle After Size Increase
Why Tabbar Hides After the Segue
Multiple File Upload with Array of Parameters Using Alamofire
Table View Controller Duplicate Itself in iOS Swift
iOS Pass Data Back from Viewcontroller2 to Viewcontroller 1 with Presentmodalsegue
Swift Save Viewcontroller State Using Coder Beyond App Close
Using Simple Ping in Swift (Ios)
Allow Users to Send Messages to Multiple Users Simultaneously in a Messaging App
Why Does It Take Such a Long Time for UI to Be Updated from Background Thread
Uitest Color of a Label (Not UI Label)
iPhone Simulator Plays Video, Real Device Won'T
Swiftui - Scrollviewreader's Scrollto Does Not Scroll
Keep a View Always on Top (Don't Scroll with Keyboard) in Iqkeyboardmanager
Attempting to Segue from Objective-C to Swift Vc
How to Crop Image in Circle Shape with Grid Inside Circle