How can I make a TextField width adapt to his content? - ios

Is there any option that make a TextField adapt to his content?

There is a way to do it manually by adjusting the frame of the textview when a change in it occurs.
var text: String = "Some text is just here..."
let size: CGSize = text.size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 14.0)])
^The code will give you the size needed for the text to be fully displayed and you can resize you textView according to it. //be aware there might be some paddings inside the textview
extension String {
func heightWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.height
}
}
^If you need dynamic height (multi-lines) constraining the width will help you with the task.
I'm not completely sure what you are trying to accomplish, but I hope this helps a little.

Create a oultet for height constraint of textview. After:
textView.delegate = self
textView.isScrollEnabled = false
func textViewDidChange(_ textView: UITextView) {
let fixedWidth = textView.frame.size.width
textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
var newFrame = textView.frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
heightTextview.constant = newFrame.size.height //update constraint constant with new height
}
textView will change height for fit multiple line content. It works well

Related

Understanding UIScrollView contentSize.height

I'm kind of confused by this. I have a very simple setup. I have a UIScrollView that is constrained to the superview of a ViewController with 0,0,0,0. And then a UILabel that is constrained to the UIScrollView with 8,8,8,8.
I have a String extension to get the height of the label with a specific font.
extension String {
func heightWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedString.Key.font: font], context: nil)
return boundingBox.height
}
}
In viewDidLoad, I set up my label. (UILabel is set for number of lines to 0 and word wrap).
let text = "some really long text" // actually really long text in my sample
let width = view.frame.width
let font: UIFont! = UIFont(name: "HelveticaNeue-UltraLight", size: 42)
let height = text.heightWithConstrainedWidth(width: width, font: font)
print("height first: \(height)") // 1080
Then I set my scrollView.contentSize to that size
scrollView.contentSize = CGSize(width: view.frame.width, height)
print("new height: \(scrollView.contentSize.height)") // 1080
But in scrollViewDidScroll, if I print out the height there
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("scrollView.contentSize.height: \(scrollView.contentSize.height)") // 3440
}
I was wondering why in scrollViewDidScroll the height of the scrollView's contentSize is 3440 and not 1080. It's 1080 after I put in the text for the label and set up the content size.
I would think if the size is 3440, I would see that after I set the scrollView's contentSize and it wouldn't change in the scrollViewDidScroll delegate method. Is this because I'm using Auto Layout and Auto Layout doesn't calculate the size of the contentSize until you start scrolling or something?

How to get the content Height of dynamically changing Text in textview?

I have a dynamically changing text in TextView.I could not be able to get the content Height of TextView.
Here is what i tried.
let height = self.tvComment.contentSize.height
print("height",height)
let contentSizeComment = self.tvComment.sizeThatFits(self.tvComment.bounds.size)
print("height",contentSizeComment)
Why it's not getting the content height of TextView?
Hope you understand my problem.
Thanks in Advance
Usethis method to get the height -
func heightForString(text:String, font:UIFont, width:CGFloat) -> CGFloat{
let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.size.height
}
in textdidchange you can use this code,in order to resize when textchange
//approxi should be the width of your textview
let approxi = view.frame.width - 90
//size is the max width and height of textview,1000 can be what ever you want
let size = CGSize(width: approxi, height: 1000)
//dont forget to put your font and size
//chey is the text of thetext view
let attributes = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 15)]
let estim = NSString(string: chey).boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
//estim is height
above it the first method,second method will come in edit
second method is
func pva() {
//what was the name of my textfield
let fixedwidth = what.frame.size.width - 40
let newsize = what.contentSize.height
self.hrightext.constant = newsize
self.view.layoutIfNeeded()
}
note: both are tested and works in swift4
Your just write code in below delegate of UITextView:-
func textViewDidChange(_ textView: UITextView!) {
let height = self.tvComment.contentSize.height
print("height",height)
let contentSizeComment = self.tvComment.sizeThatFits(self.tvComment.bounds.size)
print("height",contentSizeComment)
}
I hope it help you,
Thank you.

get height of dynamic textViews in tableView without using automatic dimensions using swift

I want to calculate the height of my textView's in a tableView dynamically to use in heightForRowAt. I DO NOT want to use automatic dimensions as it often messes up my scrolling in containerViews.
Presently I am instantiating a textView for every cell, adding the text and getting the height using:
var textViewForCellHeight = UITextView()
textViewForCellHeight.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
textViewForCellHeight.frame = CGRect(x: 0, y: 0, width: self.tableView.frame.size.width - cellHorizontalPadding - tableView.safeAreaInsets.left - tableView.safeAreaInsets.right, height: 0)
textViewForCellHeight.text = myString
textViewForCellHeight.sizeToFit()
return textViewForCellHeight.frame.size.height
Using this in heightForRowAt works fine and gives the correct height for the cell, but it expensive and slows down the tableView considerably. Is there a more efficient way to get the height of the tableView cell's dynamically with a textView?
You can simply pass your string in this function and you will get dynamic height according to your string.
func calculateHeight(inString:String) -> CGFloat
{
let messageString = input.text
let attributes : [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 15.0)]
let attributedString : NSAttributedString = NSAttributedString(string: messageString!, attributes: attributes)
let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
let requredSize:CGRect = rect
return requiredSize.height
}
Try this code:
func cellHeight(withTxt string: String) -> Float {
let textRect: CGRect = string.boundingRect(with: CGSize(width: self.view.frame.width/* Preferred textView Width */, height: CGFloat(MAXFLOAT)), options: ([.usesLineFragmentOrigin, .usesFontLeading]), attributes: [.font: UIFont(name: "Helvetica Neue", size: 17)!], context: nil)
let requiredSize: CGSize = textRect.size
//finally u return your height
return Float(requiredSize.height)
}

How to use sizeThatFits in Swift?

I have got a text view and a view like this
let lb = UITextView()
let view = UIView()
background_img_view.addSubview(about_txt)
lb doesn't have fixed height,it can be 30 or 300px,how can i use sizeThatFits to make background_img_view's height depend on lb's?
Try this:
// Get the width you want to fit
let fixedWidth = textView.frame.size.width
// Calculate the biggest size that fixes in the given CGSize
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
// Set the textView's size to be whatever is bigger: The fitted width or the fixedWidth
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
// Make the "background_img_view" height match the textView's height
background_img_view.frame.size.height = textView.frame.size.height

Swift: how to get the correct String size

I want to calculate the size of a string, to resize a UILabel. I used three different ways to calculate the size, to be exact, two ways. But I got three different results, and totally confused.
The most confusing thing is that I created a UILabel and use sizeToFit() to get the size. then I use the size to create a real UILabel and display it, but the label is truncated. Then I use sizeToFit() again to adjust the real UILabel, and the size is larger.
I doubted if it's caused by scale differences. But it is still three results on different simulators/devices.
Here's my code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let items = ["connected devices", "join session", "start host"]
let font = UIFont.systemFontOfSize(16)
var i = 0
for item in items {
let size = item.size(font: font)
print("\(size)")
let attriSize = item.sizeWithAttributes([NSFontAttributeName:font])
print("attriSize\(attriSize)")
let label = UILabel(frame: CGRect(origin: CGPoint(x: 50, y: 50 + i*50), size: size))
label.text = item
label.backgroundColor = UIColor.redColor()
label.sizeToFit()
print("\(label.bounds.size)")
view.addSubview(label)
++i
print("\n")
}
}
}
extension String {
func size(font font: UIFont) -> CGSize {
let label = UILabel(frame: CGRectZero)
label.text = self
label.font = font
label.sizeToFit()
let size = label.bounds.size
return size
}
}
and the results are
(137.333333333333, 19.3333333333333)
attriSize(137.0859375, 19.09375)
(144.666666666667, 20.3333333333333)
(84.3333333333333, 19.3333333333333)
attriSize(84.265625, 19.09375)
(89.0, 20.3333333333333)
(70.0, 19.3333333333333)
attriSize(69.765625, 19.09375)
(73.6666666666667, 20.3333333333333)
I really want to know what's wrong with sizeToFit(). Any help is appreciated.
Hi it is working example that can help you :
let fixedWidth = textView.frame.size.width
textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = textView.frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
textView.frame = newFrame;

Resources