Re-arrange UILabel after new line - swift

I have a label which gets its text from textfield and has a limit in width of imageview where it is on. I want to add a new line when the limit has reached. However, i couldn't do it with "\n" and wordwrapping function. In addition, i need to set UILabel's height and width to exactly texts size. I mean if it has two lines height should for two line only not much and exact same for the width property.
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if(imageview.frame.width > label.frame.width + 2)
{
label_test.text = "\(label.frame.width)"
label.text = textfield.text
if(imageview.frame.width < label.frame.width + 20)
{
label.lineBreakMode = .byWordWrapping
label.text = textfield.text! + "\n"
label.textAlignment = NSTextAlignment.center;
}
}
return true
}

Why can't you use lineBreakMode ? In my opinion you should define a basic setup in your viewDidLoad or so :
func viewDidLoad() {
//Your stuff
label.frame.size.width = imageview.frame.width //Define max width
label.numberOfLines = 0 //Set infinite number of lines
label.lineBreakMode = .byWordWrapping
}
Then in your textfieldShouldEndEditing you set the text and the height
label.text = textfield.text
label.sizeToFit() //The height is adjusted

Related

How do I Fade Label out at end instead of replacing end with "..." if it's too long / How to use GoogleToolboxForMac

I've found a solution with GTMFadeTruncatingLabelTest from GoogleToolboxForMac but don't really understand how to use it and I don't find anything about it
but if you have another solution besides of this one
If you can't help me with GoogleToolboxForMac feel free to suggest other solution
Should kinda look like this at the end:
I am not sure about the GTMFadeTruncatingLabelTest but I can offer an alternative solution.
Steps
Check if the label's text is going to be truncated
If 1 is true, Create a CAGradientLayer that goes from Opaque to Transparent
Apply the gradient layer as a mask to the UILabel
Implementation
If you don't want to read the rest, just grab the code from this repo
I wrapped step 1, 2 and 3 from above in a custom UILabel subclass. The reasoning is explained in the comments.
class FadingLabel: UILabel
{
// Add a property observer for text changes
// as we might not need to fade anymore
override var text: String?
{
didSet
{
// Check if the text needs to be faded
fadeTailIfRequired()
}
}
// Add a property observer for numberOfLines changes
// as only 1 line labels are supported for now
override var numberOfLines: Int
{
didSet
{
// Reset the number of lines to 1
if numberOfLines != 1
{
numberOfLines = 1
}
}
}
override func layoutSubviews()
{
super.layoutSubviews()
// The label's frame might have changed so check
// if the text needs to be faded or not
fadeTailIfRequired()
}
/// The function that handles fading the tail end of the text if the text goes
/// beyond the bounds of the label's width
private func fadeTailIfRequired()
{
// Reset the numberOfLines to 1
numberOfLines = 1
// Prevent processing fading when the library is in the middle of
// processing the string to truncate the ellipsis
if !isTruncatingEllipsis
{
// Check if the label's has it's width set and if the text goes
// beyond it's width plus a margin of safety
if bounds.width > CGFloat.zero && intrinsicContentSize.width > bounds.width + 5
{
// Fade label works better with this setting
allowsDefaultTighteningForTruncation = true
// Initialize and configure a gradient to start at the end of
// the label
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.colors = [UIColor.white.cgColor, UIColor.clear.cgColor]
gradient.startPoint = CGPoint(x: 0.8, y: 0.5)
gradient.endPoint = CGPoint(x: 0.99, y: 0.5)
// Apply the gradient as a mask to the UILabel
layer.mask = gradient
// Remove ellipsis added as the default UILabel truncation character
removeEllipsis()
// We do not need to go beyond this point
return
}
// If the text has not been truncated, remove the gradient mask
if originalText == text
{
// Remove the layer mask
layer.mask = nil
}
}
}
/// Keep removing 1 character from the label till it no longer needs to truncate
private func removeEllipsis()
{
isTruncatingEllipsis = true
// Keep looping till we do not have the perfect string length
// to fit into the label
while intrinsicContentSize.width > bounds.width
{
// Drop the last character
text = String(text!.dropLast())
}
isTruncatingEllipsis = false
}
}
Then you can use it like a regular UILabel, for example:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let fadingLabelWithLongText = FadingLabel()
view.addSubview(fadingLabelWithLongText)
fadingLabelWithLongText.text = "Fading label with text more than it's bounds can handle"
fadingLabelWithLongText.textColor = .white
fadingLabelWithLongText.frame = CGRect(x: 20, y: 90, width: 250, height: 50)
let regularLabelWithLongText = UILabel()
view.addSubview(regularLabelWithLongText)
regularLabelWithLongText.text = "Regular label with text more than it's bounds can handle"
regularLabelWithLongText.textColor = .white
regularLabelWithLongText.frame = CGRect(x: 20, y: 160, width: 250, height: 50)
let fadingLabelWithShortText = UILabel()
view.addSubview(fadingLabelWithShortText)
fadingLabelWithShortText.text = "Fading label with text that fits"
fadingLabelWithShortText.textColor = .white
fadingLabelWithShortText.frame = CGRect(x: 20, y: 230, width: 250, height: 50)
let regularLabelWithShortText = UILabel()
view.addSubview(regularLabelWithShortText)
regularLabelWithShortText.text = "Regular label with text that fits"
regularLabelWithShortText.textColor = .white
regularLabelWithShortText.frame = CGRect(x: 20, y: 300, width: 250, height: 50)
}
Output
Limitation
This way only supports single line UILabels
Update
Added a function to remove the default truncation method of using ellipsis (three dots) by UILabel with this function.
/// Keep removing 1 character from the label till it no longer needs to truncate
private func removeEllipsis()
{
isTruncatingEllipsis = true
// Keep looping till we do not have the perfect string length
// to fit into the label
while intrinsicContentSize.width > bounds.width
{
// Drop the last character
text = String(text!.dropLast())
}
isTruncatingEllipsis = false
}
This function has been updated in the original code and repo mentioned above.
I Think the easiest way is to use the following code:
titleLabel.adjustsFontSizeToFitWidth = false
titleLabel.lineBreakMode = .byClipping
It automatically fades the last words if applicable and text size has more width than UILabel!
thanks to thi

Layout programmatically created UILabels in a UIView

I have this:
Created via this piece of code:
// Add hashtag collection to a post
func addHashtags(container: UIView, constraint: NSLayoutConstraint) -> Void {
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width - 16 - 16
var currentOriginX: CGFloat = 0
var currentOriginY: CGFloat = 0
for j in 0..<self.pseudo.count {
if currentOriginY < 144 {
// Create a new label
let labelHashtag = RoundedLabel()
labelHashtag.rounded = true
tagLabels.append(labelHashtag)
print(tagLabels.count)
// Set its properties (title, colors, corners, etc)
labelHashtag.text = pseudo[j] as? String
labelHashtag.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
labelHashtag.textAlignment = .center
labelHashtag.textColor = UIColor.black
labelHashtag.backgroundColor = UIColor.white
labelHashtag.layer.borderColor = UIColor(red:0.88, green:0.88, blue:0.88, alpha:1.0).cgColor
labelHashtag.layer.borderWidth = 1
// Set its frame width and height
labelHashtag.frame.size.width = labelHashtag.intrinsicContentSize.width + tagPadding
labelHashtag.frame.size.height = tagHeight
// Add it to the scroll view
container.addSubview(labelHashtag)
// If current X + label width will be greater than container view width
// .. move to next row
if (currentOriginX + labelHashtag.frame.width > screenWidth) {
tagLabels[0].textColor = .red
print("übrig")
print(screenWidth - currentOriginX)
currentOriginX = 0
currentOriginY += tagHeight + tagSpacingY
}
// Set the btn frame origin
labelHashtag.frame.origin.x = currentOriginX
labelHashtag.frame.origin.y = currentOriginY
// Increment current X by btn width + spacing
currentOriginX += labelHashtag.frame.width + tagSpacingX
} else if currentOriginY == 90 {
}
// Update container view height
constraint.constant = currentOriginY + tagHeight
}
container.layoutIfNeeded()
}
I want to center all items in each row. I imagine I have to calculate the remaining width of my UIView and add a margin to the first item.
How can I add a margin to my UILabel? I can access it via tagLabels[0] and I think I know how to calculate the remaining width, but I don't know how I can add the margin to it.

How can I increase the y of a label, in swift?

So I am very new in Swift and I can't figure out how to increase the y value from a label.
I am trying to show in a label, some messages that a user types in an input... like a chat view.
So I have this code, but it puts all the messages one above the other:
I know that it is very messy, I am sorry for that.
Thanks!
//my label
#IBOutlet weak var label: UILabel!
//my text field
#IBOutlet weak var textF: UITextField!
#IBAction func buttonPressed(sender: AnyObject) {
//create a variable(input) to store my text from the TextField
var input = textF.text
//put that text in the label
label.text = input
var label2 : UILabel = UILabel(frame: CGRectMake(20, 20, 200, 21))
var isSendMessage: Bool = true {
didSet {
if isSendMessage {
var input = textF.text
label.text = input
textF.text = " "
// self.view.label.origin.y += 10
} else {
var input = textF.text
label2.text = input
textF.text = " "
}
}
}
label2.center = CGPointMake(160, 284)
label2.textAlignment = NSTextAlignment.Center
self.view.addSubview(label2)
//empty text field
textF.text = " "
label2.center = CGPointMake(160, 284)
label2.textAlignment = NSTextAlignment.Center
label2.text = input
//add it to the view
self.view.addSubview(label2)
}
Try this
Don't update Y axis directly as if your Y value is greater than the screen height then label will go off the screen.
Try the following code.
// Taking height and width of the screen
var height = UIScreen.mainScreen().bounds.size.height;
var width = UIScreen.mainScreen().bounds.size.width;
var x = 164.0 // Fixed height of the label
if x < height
{
x += 20.0 // Incrementing height value
if (height - 20) >= x // Checking the difference between screen height and x, so it doesn't go beyond the screen.
{
label.frame = CGRectMake(20.0, x, 200.0, 21.0)
self.view.addSubview(label)
}
else
{
// Setting default height
label.frame = CGRectMake(20.0,164.0, 200.0, 21.0)
self.view.addSubview(label)
}
}
Hope this will be helpful.
In a quick answer to your question, if you are just looking to change the position on the y-axis you can use the property .y under .center
self.yourLabel.center.y = self.yourLabel.center.y + 10

create an equal space between labels in the scrollview with swift

I am creating a menu of the same style as the kiosk play Application
I would like the same space between labels, for I dynamically creates, I try SEVERAL way but it does not work.
I size of their label and I added the padding but it does work.
Here is the result
here is my code
func menu (value: [String]){
var pos: CGFloat = 50.0
var index: Int = 0
for index = 0; index < value.count ; index++ {
self.titleLabel = UILabel()
self.titleLabel.text = "\(value[index])"
self.titleLabel.textColor = UIColor.blackColor()
self.titleLabel.backgroundColor = UIColor.blueColor()
self.titleLabel.font = UIFont(name: "MarkerFelt-Wide", size: 20)
self.titleLabel.sizeToFit()
//width of the label
var widhtLabel = self.titleLabel.frame.size.width
// add padding
self.titleLabel.frame.origin.x = widhtLabel + pos
self.scrollViewMenu.addSubview(self.titleLabel)
pos += 150.0
println()
}
self.scrollViewMenu.contentSize = CGSize(width: self.titleLabel.frame.origin.x + 220, height:0)
}
thanks

is it possible to set the UILabel distance between the line?

Is it possible to set a UILabel's distance between the line, as i had a UILabel contain 3 lines, and linebreakmode is wordwrap?
If you're referring to "leading", which refers to the gap between lines of type - you cannot change this on a UILabel. That is inferred from the front of the label itself. Some people have tried to create categories to override the "leading" property of the UIFont for the label but it doesn't actually work when rendering.
If you really need to control the vertical spacing between lines of text then your best bet is to programmatically drop 1 UILabel per line of fixed width and control the vertical gap yourself.
Here is how you can set line spacing using interface builder and programatically as well.
From Interface Builder:
Programmatically:
SWift 4
Using label extension
extension UILabel {
// Pass value for any one of both parameters and see result
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = lineHeightMultiple
let attributedString:NSMutableAttributedString
if let labelattributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Line spacing attribute
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
Now call extension function
let label = UILabel()
let stringValue = "is\nit\npossible\nto\nset\nthe\nUILabel\ndistance\nbetween\nthe\nline?"
// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0
// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0
Or using label instance (Just copy & execute this code to see result)
let label = UILabel()
let stringValue = "is\nit\npossible\nto\nset\nthe\nUILabel\ndistance\nbetween\nthe\nline?"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString