Make label only as wide as it needs to be? - ios

I have 3 labels next to each other inside a horizontal stack view like this
The first and last label are going to be dynamically filled with a word of variable length, while the middle one is always going to contain the word "with", for example: "Coding with Swift!"
I don't want there to be extra space between each word as it would look strange if the words are short. Is there any way to make the labels only be as wide as they need to be to fit their text? That way it all looks like one label (except I'm making the middle label have smaller text).

Add 3 labels inside a UIView instead of stack view.
And set constraints as shown in image.

How about using autolayout?
You could give a horizontal space of 0 between the labels and a constraint of width for the middle one.

If u wish to have different fonts for the content in a label you can use NSAttributedString
let boldFontDict:[String: AnyObject] = [NSForegroundColorAttributeName : UIColor.black, NSFontAttributeName: <UI Font>]
let 1stString = NSAttributedString(string: "Hello")
let 2ndString = NSAttributedString(string: "hii", attributes: boldFOntDict)
let finalAttrStr = NSMutableAttributedString(attributedString: 1stString)
finalAttrStr.append(2ndString)
myLabel.attributedText = finalAttrStr

You can take one label instead of taking three label
and and set the text on label as
label.text= firstLabel.text + "with" + lastLabel.text

You can use autolayout to fix this problem.

Related

How to align Right-Justify UILabel?

Remark:
Implementing:
myLabel.textAlignment = .right
does not solves my problem, that is not what I am asking for.
What I am trying to achieve is to let the alignment for the label to be Right-Justify.
To make it more clear:
That's how left alignment looks:
And that's how justify alignment looks:
if you are not seeing any difference between the tow screenshots, you could recognize it by the right (trailing) constraint of the label, you will notice in the second screenshot the whole width of the label has been filled by the text.
As shown in the second screenshot, letting the label to be justified will make it Left-Justify by default, i.e the last line alignment is left.
How can I make let the label to be justified to the right? In other words, I want the text to be just like the 2nd screenshot except that I want the last short line to be shifted to the right.
If you wondering what is the purpose of doing such a thing, it would be appropriate for right to left languages.
Thanks to #user6788419 for mentioning the appropriate answer.
For achieving it, you should work with NSMutableParagraphStyle:
An object that enables changing the values of the subattributes in a
paragraph style attribute.
It gives you the ability to the alignment and baseWritingDirection simultaneously, which leads to the desired output:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var lblDescription: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let text: NSMutableAttributedString = NSMutableAttributedString(string: "In vertebrates, it is composed of blood cells suspended in blood plasma. Plasma, which constitutes 55% of blood fluid, is mostly water (92% by volume), and contains dissipated proteins...")
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .justified
paragraphStyle.baseWritingDirection = .rightToLeft
paragraphStyle.lineBreakMode = .byWordWrapping
text.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, text.length))
lblDescription.attributedText = text
}
}
The output would be:
There is not ENUM available for right justified!
You have to choose from NSTextAlignmentLeft,NSTextAlignmentRight,NSTextAlignmentCenter,NSTextAlignmentJustified,NSTextAlignmentNatural.
You have added screenshot of xcode's interface builder! once check it in simulator or device.
If you want space at left or right side in label with justified text then you can play with edge insets.
For example Left padding in label.

How to make multi-line UILabel text fit within predefined width without wrapping mid-word

I have a UILabel carefully laid out in Interface Builder with proper height and width constraints. The number of lines is set to 4. The wrapping is set to word wrap. The text is "CHECKED". The font size is very large and thus it only fits "CHECKE" and the "D" is on the second line. Writing "Checked" instead of "CHECKED" lets the font shrink (as intended) so that the whole word fits. But (the text is user given and it can be expected that the user writes fully uppercase words) having uppercase words the label does not break it/shrink the font as expected.
Do you have a suggestion as to what I might have missed? Capitalising the words (thusly only having the first letter uppercase) does work, but is not what the client wants.
Updated question
The problem seems to be unrelated to having uppercase or lowercase text. My problem could be solved by an answer to the following question:
How to make (ideally with the help of only Interface Builder) the UILabel text shrink trying to fit full words within all available lines without wrapping the text mid-word?
If the text "CHECKED" is too wide for a label (with more than 1 line available) it should shrink the font size instead of breaking the "D" and wrapping the single letter to the next line.
If the text is "one CHECKED two" and the single word "CHECKED" is already too wide for a label (with more than 1 line available) it should break between all words and shrinking the font size so that "CHECKED" still fits the middle line.
Avoiding:
one
CHECKE
D two
Thank you very much!
Here is a UILabel subclass that will find the largest word in the labels text, use the boundingRect function of NSString to see how large that one word will be with the current font, and drop the font size until it fits the width.
class AutosizingMultilineLabel: UILabel {
override func layoutSubviews() {
super.layoutSubviews()
self.adjustFontToFitWidth()
}
func adjustFontToFitWidth() {
guard let currentFont = self.font else { return }
let minimumFontSize: CGFloat = floor(self.minimumScaleFactor * currentFont.pointSize)
var newFontSize = currentFont.pointSize
var theNewFont = currentFont
if let text = self.text, let longestWord = text.components(separatedBy: " ").max(by: {$1.count > $0.count})?.replacingOccurrences(of: "\n", with: "") {
let nsString = longestWord as NSString
while newFontSize > minimumFontSize {
theNewFont = currentFont.withSize(newFontSize)
let boundingRect = nsString.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [.font: theNewFont],
context: nil)
if ceil(boundingRect.size.width) <= self.bounds.size.width {
break
}
newFontSize -= 1
}
self.font = theNewFont
}
}
}
When the word is bigger than the line, word wrap doesn't work. If it doesn't fit on this line, it won't fit on the next line. (same word, same size, same line size). To make it fit, the label will start putting letters on the next line.
If you allow multiple lines on your label, the OS will try to fill the lines before adjusting the font size.
I think you're just running into a limitation on Autoshrink.
In Interface Builder:
add a new UILabel with Width: 230 and Height: 280
set the Font to System 44.0
set Line Break: Truncate Tail
set Autoshrink: Minimum Font Scale at 0.15
set the text of the label to test CHECKED lines
Now, drag the handle on the right edge of the label left and right... when it gets too narrow, the word CHECKED will break onto the next line.
Change CHECKED to checked and do the same thing. You should see the same behavior.
Now, try dragging the Bottom edge up and down. With either CHECKED or checked, you should see the Font Size auto shrink.
So... to do what you're trying to do, you might have to skip Autoshrink and instead do some code calculations.
Edit: further visual of what goes on...
Start with above values, but set the Height of the label to 170 - gives it just a little vertical padding.
Now, drag the left edge to make it narrower.
When you reach the end of the word CHECKED, and keep going, you will see the font shrink until it gets small enough that there is space for it to wrap to a 4th line.
I think you're going to need some code to get exactly what you need.

Align UILabel text to a specific character

I'm using a UILaber showing a second countdown in a very large font (size 240). The displayed string is formatted "xxx.xx", with x's being characters 0-9. I want to align the text to the dot-chatecter (.) in the string that showing in the label. I use textAlignment as .Center in the label, but some strings differ in actual displayed length, causing the dot-character to be shifted left and right when the string is updated. F.x. the textContainer for a "1" is smaller than an "8".
Is it possible to do this kind of character allignment?
Interesting Question mate:
Please find a solution below:
Basically what i've done here is:
Using Storyboard i've taken 3 Vertical Stack Views inside a Horizontal Stack View.
Just center align the second vertical stack view with static width and other stack views will adjust accordingly.
Rest you can follow the screenshot attached for constraints.
No constraints required for labels, just text align according to your need.
Cheers!
let attributedStringOne = NSAttributedString.init(string: "XXX", attributes: [NSAttributedStringKey.baselineOffset: 0])
let attributedStringTwo = NSAttributedString.init(string: ".", attributes: [NSAttributedStringKey.baselineOffset: label.frame.height / 4])
let attributedText = NSMutableAttributedString.init()
attributedText.append(attributedStringOne)
attributedText.append(attributedStringTwo)
label.attributedText = attributedText
baselineOffset is NSNumber type. So you can set how much you want from baseline.
attach three labels together..
label1|labelDot|label2 which will be matching your XX.XXX
right align your label1, fix your labelDot, left align your label2

how to make UITextView text alignemnt right and Justified at the same time

I need my long text inside UITextView to be aligned right and Justified at the same time . But I notice that I could just select right or justified .How can I have both Alignments for my UItextView at the same time ?
You can do it like this (Swift 3,4):
var yourString = String()
let yourTextView = UITextView()
let attrText = NSMutableAttributedString(string: yourString)
let paragraph = NSMutableParagraphStyle()
paragraph.baseWritingDirection = .rightToLeft
paragraph.alignment = .justified
attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraph, range: NSMakeRange(0, yourString.length))
yourTextView.attributedText = attrText
The best option available for your requirement at the moment is this
You cannot achieve both alignment at the same time, But you can add a right alignment when entering the text in the textview, after you finished editing the textview set the text alignment to justify,
So Whenever you start editing the textview use right alignment and once you have finished editing set justify , simple :)
Hack it!(kidding:)). Set text alignment to the justified, set width that is less than screen width, move the text view to the right edge of the screen. Voila, it's right aligned and justified. Good luck!

Label in a UITableViewCell, change second line font size, add margins?

I have a tableview that uses UITableViewCell and is populated by data from parse.com. In the UITableViewCell there is a LABEL that has 2 lines, that shows data from parse.com.
I am wondering if it is possible to change the font size of the second line of the LABEL (leave the first line's font size the same), also is there is there a way to add margins to the left and right of the label?
EDIT: mistyped, i want to change the font size of the second line of a LABEL, as well as add margins to the left and right of the label.
In my solution I have made an used the attributedText of the UILabel to add attributed string to the label
var attributedString = NSMutableAttributedString(string:"My first line \n")
//creating NSMutableAttributedString that will be later appended with your second line
var secondLine = "My attributed second line"
let secondLineAttribute = [NSFontAttributeName : UIFont(name: label.font.fontName, size: 22)!]
//replace 22 with the size of text you want for second line
var newAttributedSecondLine: NSAttributedString = NSAttributedString(string: secondLine, attributes: secondLineAttribute)
attributedString.appendAttributedString(newAttributedSecondLine)
label.attributedText = attributedString
Dont forget to add label.numberOfLines=2 before the above code
Try this:
cell.textLabel!.font = UIFont(name: "Gotham-Book", size: 16)
Hope this might help you.
UITableViewCell has two labels textLabel and detailTextLabel if created with Subtitle style. Configure detailTextLabel as you like. Otherwise make your own UITableViewCell subclass.

Resources