Adjust label based on Text given in Text view in swift 3? - ios

I am working on Photo Editing App and i am trying to adjust label Based on Text given in Text View . I have tried Lots of code but it did not work for me. i want to add Label on Image Which is based on text given in my textview as shown in Image given below. I am unable to set width and height of label based on textview's text. I have Tried Following code. Some one please help.
let newWidth: CGFloat = CGFloat(txtView.text.boundingRect(with: txtView.frame.size, options: .usesLineFragmentOrigin, context: nil).size.width)
let Label = UILabel(frame: CGRect(x: 100, y: 100, width: newWidth, height: 100))
imgView?.addSubview(Label)
I have also tried
var maximumLabelSize = CGSize(width: 296, height: FLT_MAX)
var expectedLabelSize: CGSize = yourString.size(withFont: yourLabel.font, constrainedTo: maximumLabelSize, lineBreakMode: yourLabel.lineBreakMode)
//adjust the label the the new height.
var newFrame: CGRect = yourLabel.frame
newFrame.size.height = expectedLabelSize.height
yourLabel.frame = newFrame

I have solved my issue using JLStickerTextView but in this repository its not compatible for Swift 3.0 so i have made changes in project and you can find out Working Project without any errors from her https://github.com/khush004/StickerView/tree/master

func calcheight(strin:String) -> CGFloat
{
let label = UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.text = strin
label.sizeToFit()
return label.frame.height + 2
}

Related

Swift - Rotated UITextView autosize problem

I use this function to make UITextView auto fit text content when typing. It works fine when the TextView is horizontal but does not work correctly when TextView is rotated. Any ideas how it can be fixed?
func textViewDidChange(_ textView: UITextView) {
let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}
According to the docs:
When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.
I think that might be why your code doesn't work - frame is undefined after you have applied a transform.
Try setting the transform back to identity before setting the frame:
let transform = textView.transform
textView.transform = .identity
let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
textView.transform = transform
I have seen UITextView sometimes does not play good with transformations.
Wrap your UITextView in a UIView. Set top, leading, bottom and trailing constaints of UITextView to UIView. Perform all the transformations on UIView. You should be good to go.
I have the same issue and I saw this problem, after that I fixed it like this;
extension UITextView {
func calculateSize() {
let currentTransform = transform
transform = .identity
let currentCenter = center
let fixedWidth: CGFloat = font == nil ? 300 : text.widthOfString(usingFont: font!) + 16 // 300 for the worst case scenario and 16 is for leading and trailing spaces for content
sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
let newSize = sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
var newFrame = frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
frame = newFrame
center = currentCenter
transform = currentTransform
layoutIfNeeded()
}
}

Measuring the height of lines in UITextView

I am trying to measure the height of lines to place an overlay over specific text in a UITextView. Specifically what I mean by lines is text delimitated with \n. So one line can actually span multiple lines and that is what I am trying to measure. I have tried a few different approaches, however, I can't seem to calculate the height correctly. Another weakness with my current approaches is it has to be all calculated on the main synchronous thread which is less than ideal because I have a lot calculations to do.
EXAMPLE UI APPROACH
measurement.font = UIFont(name: "Menlo", size: 16)
measurement.frame = CGRect(x: 0, y: 0, width: 10000, height: 50)
func heightForString(line: String) -> CGFloat {
var height : CGFloat = 0
measurement.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 10000)
measurement.sizeToFit()
height = measurement.frame.height
print(height, lineHeight)
measurement.frame = CGRect(x: 0, y: 0, width: 10000, height: 50)
return height
}
// Comparing the returned height to measurement.font?.lineHeight and padding shows the results make little sense... :(
EXAMPLE PRINT
Should be 1 line
30.0 18.625
Should be 3 lines
43.6666666666667 18.625
func heightForString(line: String) -> CGFloat {
let textView = UITextView()
let maxwidth = UIScreen.main.bounds.width
textView.frame = CGRect(x:0,y: 0,width: maxwidth,height: CGFloat(MAXFLOAT))
textView.textContainerInset = UIEdgeInsets.zero
textView.textContainer.lineFragmentPadding = 0
textView.font = UIFont(name: "Menlo", size: 16)
textView.text = line
textView.isScrollEnabled = false
textView.sizeToFit()
return textView.frame.size.height
}

How can i increase the height of textview in upper side instead of regular bottom side?

I want to increase height of textview according content of textview increase. i tried different way but i did't get solution to increase height in up direction. Attached image
Change frame of UITextView in textViewDidChange delegate method,
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 textViewFrame = textView.frame
textViewFrame = CGRect.init(x: textViewFrame.origin.x, y: textViewFrame.origin.y+textViewFrame.height-newSize.height, width: max(newSize.width, fixedWidth), height: newSize.height)
textView.frame = textViewFrame
}
It will increase size of UITextView from bottom.
After setting the text, so in the viewWillLayoutSubView()
let contentSize = textView.sizeThatFits(textView.bounds.size)
After that you will be able to use the contentSize Height:
height: contentSize.height

swift 3 ios : UILabel

I'm trying to create a UILabel, with dynamic height
this is my code :
label1.text = Message
label1.textColor = UIColor.white
let font = UIFont.systemFont(ofSize: 17.0)
label1.font = font
label1.textAlignment = .center
label1.lineBreakMode = NSLineBreakMode.byWordWrapping;
label1.numberOfLines = 0;
label1.sizeToFit()
label1.frame = CGRect(x: 0, y:40 , width: 270, height: label1.frame.height)
however, my label stay with one line, where my Message is about 3 lines
so what could be the best solution for this problem?
The best solution would be using constraints.
Either directly in the InterfaceBuilder or via code.
(SnapKit would be a good and easy way to build constraints via code)
Try
let size = label1.sizeThatFits(CGSize(width: 270, height: 100000))
label1.frame = CGRect(x: 0, y: 40, width: 270, height: size.height)
for the last two line of your code.
you can do it with storyboard
label height relation to greater than or equal

Setting dynamic height on UItextview to fit content programmatically

Just by programmatically coding, I'm trying to achieve something like below image. TextView and ContainerView are embedded in scrollview although it is not shown in the image.
Here is my code for this.
override func viewDidLoad() {
super.viewDidLoad()
let margin = CGFloat(10)
textView = UITextView()
textView.text = "asdadaasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadaadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadadasdadadaddadd"
let contentSize = textView.sizeThatFits(textView.bounds.size)
textView.frame = CGRectMake(margin, 0, self.view.frame.width - 2 * margin, contentSize.height)
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height - 50))
let containerView = UIView(frame: CGRectMake(margin, contentSize.height + margin, self.view.frame.width - 2 * margin, self.view.frame.height))
let button1 = UIButton(frame: CGRectMake(margin, contentSize.height + containerView.frame.height + 2 * margin, (view.frame.width - 2 * margin)/2, 30))
scrollView.contentSize = CGSize(width: self.view.frame.width, height: button1.frame.origin.y + button1.frame.height + margin)
self.view.addSubview(scrollView)
scrollView.addSubview(textView)
scrollView.addSubview(containerView)
scrollView.backgroundColor = UIColor.blueColor()
containerView.backgroundColor = UIColor.yellowColor()
textView.backgroundColor = UIColor.greenColor()
}
The problem is that textview's height is not dynamic to show all content in textview.
I've confirmed that if I add below code in viewdidappear, it does make the height of textview dynamic but it is stacked under Container view because below code runs after ViewDidLoad configured everything.
let contentSize = textView.sizeThatFits(textView.bounds.size)
textView.frame = CGRectMake(margin, 0, self.view.frame.width - 2 * margin, contentSize.height)
What would be the best approach for this kind of problem?
I think this is caused due to rendering order in viewdidload but I'm not 100% sure. It would be great if someone can talk about rendering order too.
To answer the original question, your call to sizeThatFits has no idea how tall the TextView should be because it has no idea how wide you want it to be. I think before the sizeThatFits line you want the following:
textView.frame.size.width = self.view.frame.width - 2 * margin

Resources