How to write underscores with spaces between them? - ios

This is how I define my mask in code:
and this is how it looks with prefix +48. Why there is no space between characters? Is it something wrong with my character? It doesn't matter what font I use... it is always the same.

It doesnt matter what font I use...
Clearly you haven't tried every font. If you type in some underscores in that website, you will find exactly which fonts have underscores that are separated, and which don't. For example, DevanagariSangamMN is a font that does have separated underscores.
let view = UITextField(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
view.font = UIFont(name: "DevanagariSangamMN", size: 16)
view.text = "___ ___ ___"
PlaygroundPage.current.liveView = view
Of course, the more "proper" way of doing this is to adjust the character spacing, by giving it the characters a positive kern value.
That looks like a UITextField, so you can set its defaultTextAttributes:
yourTextField.defaultTextAttributes = [
NSAttributedString.Key.kern: 2
]

Related

NSAttributedString Drawing - How Many Lines?

I am drawing text within a PDF using this method:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
paragraphStyle.lineBreakMode = .byWordWrapping
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: UIFont(name: "MySpecialFont", size: 16)!,
NSAttributedString.Key.foregroundColor: UIColor.black
]
let attributedText = NSAttributedString(
string: myTextArray.first,
attributes: textAttributes
)
let textRect = CGRect(
x: 400,
y: 40,
width: 80,
height: 40
)
attributedText.draw(in: textRect)
Above draws the text fine. However, sometimes, the string passed on to it seem to be too long and go on for 3 lines instead of 2. In these cases, I want to textRect to be taller. Basically to know how many lines it would take so textRect could be adjusted.
There are several functions within NSAttributedString that gives string length, but thats the length if it was in a single line.
Is there a way to know how many lines the final attributedText would take inside textRect?
Use NSAttributedString.boundingRect(with:options:context:) to compute the size required. You should pass .usesLineFragmentOrigin as an option so that it'll compute it for multiple lines. Pass the width you want; the height doesn't really matter, because it'll expand the height to contain the full string, and you can use that to work out your final rectangle.
That said, from your description, it sounds like you can just make the height very large (10,000 is the usual value; but maybe you want to just give room for three lines). Since you're just drawing here; it shouldn't matter if the available rect is taller than required. It only matters if it's shorter.

How to force word wrapping of UILabel that adjusts font size and is multiline

The problem I am facing is that UILabel will break line in the middle of the word although I am using word wrapping.
You can create a new project and replace content of view controller to see the result:
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
label.center = CGPoint(x: view.frame.midX, y: view.bounds.midY)
label.numberOfLines = 2 // Setting this to 1 produces expected result
label.lineBreakMode = .byWordWrapping
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
view.addSubview(label)
label.text = "Singlewordtext"
label.backgroundColor = .red
}
This produces 2 lines of text which is broken in the middle of the word. The reason this naturally happens is because the word itself is wider than the label itself so it makes sense (I guess). But I would hope that it would use adjustsFontSizeToFitWidth and minimumScaleFactor prior to breaking it. If I set it to single line (label.numberOfLines = 1) I get expected result which is that the text will shrink instead of break. Note that doing so in this case will fit all of the text inside the label.
The question is, is there a configuration on UILabel to prevent line break in such case? Or is there some other elegant solution?
A current result:
Desired result (produced by using label.numberOfLines = 1):
Do note that I still do need to have 2 lines enabled to nicely display for instance label.text = "Three words fit".

Double check mark similar to Whatsapp's read status

How to make a double check marks in UILabel through
unicode chack mark (U+2713), without any image
To do this with Unicode is not a problem, how to make it similar to whatsapp's read status? how to do letter spacing or remove space beetween two unicode symbol?
You can achieve this using NSAttributedStringKey.kern…
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
label.backgroundColor = .white
label.attributedText = NSAttributedString(string: "✓✓", attributes: [.kern: -6])
From Apple's docs…
The value of this attribute is an NSNumber object containing a floating-point value. This value specifies the number of points by which to adjust kern-pair characters. Kerning prevents unwanted space from occurring between specific characters and depends on the font. The value 0 means kerning is disabled. The default value for this attribute is 0.

Dynamically center 2 lines of text programmatically with roughly equal length per row

My situation is that I have a line of text that can vary in length due to localization. This will need to be displayed on the screen such that each line is roughly of equal length, and is centered.
This is my very long line.
Should look like this
This is my
very long line.
So I took a crack at this and got something that works the way I want it now.
I take a localized string, set it to an empty label, and find out what it's size is. (The orange is just for illustrative purposes)
With the size of the label, I then divide it by 1.8 which gives me some buffer room to account for inconsistent word sizes (again, I don't know what will be here in advance). Finally, I multiply the height by 2.0, and set that as my new frame. Finally, I add it to the view.
This has held up with a few sample strings, though it would need to be revised to handle more than 2 lines (currently, not an issue).
let text = NSLocalizedString("This is my very long line of text.", comment: "")
let instructionLabel = UILabel()
instructionLabel.text = text
instructionLabel.textAlignment = .center
instructionLabel.backgroundColor = .orange
instructionLabel.numberOfLines = 0
let size = instructionLabel.intrinsicContentSize
let newSize = CGSize(width: size.width / 1.8, height: size.height * 2.0)
let rect = CGRect(x: 20, y: 100, width: newSize.width, height: newSize.height)
instructionLabel.frame = rect
view.addSubview(instructionLabel)
Which produces the following output:
And an even longer one:
Just for some variety, this is the second string above, but in Arabic:
You could do this to set alignment.
myLabel.textAlignment = .center
Also set the number of lines to 0. And if you want a specific width, set the preferredMaxLayoutWidth property like so:
myLabel.preferredMaxLayoutWidth = 80
myLabel.numberOfLines = 0
If you want it to work for arbitrary localizations (assuming languages that use spaces), you would need an algorithm that split the text on spaces and then loop through each combination of top and bottom text, measuring its width, to see what gave the most evenly distributed sizing. This feels like overkill.
Having done a fair amount of localization, the better bet is to manually insert \n characters in the .strings file to adjust breaks that aren't visually pleasing. Relying on a fixed width will work for many languages, but won't give you the flexibility you're looking for.

UILabel with no word wrapping

I have a UILabel that I want to clip text on a line basis. Or, a label in which it does not wrap unless I discretely pass in a "\n"
Here is code that I am currently working with:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 20, height: 200))
label.numberOfLines = 0
label.text = "ABCDEFGHIJKLMNOP" + "\n" + "1234567890123456789"
label.lineBreakMode = // None seem to accomplish what I am looking for
So this would have a label with exactly two lines of text, with each line clipping the end of the text.
Is this possible to do without having to a subview for each line?
That's a really interesting requirement you are looking for. Unfortunately, I don't think that natively Apple supports "removing" the option for word wrapping. You will need to use a label for each line, use .byTruncatingTail, and limit the numberOfLines to 1 (default). Don't use 0 (From apple's quick help: "To remove any maximum limit, and use as many lines as needed, set the value of this property to 0").
You might find some third party code through CocoaPods/etc. to help expedite it.
I think you should do this:
Note: Swift 3 Code.
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 20, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.text = "ABCDEFGHIJKLMNOP" + "1234567890123456789"
label.sizeToFit()
view.addSubview(label)
The output should be similar to:
Hope that is the general solution for your case.

Resources