简体   繁体   中英

Change text of UILabel depending on label width

Xcode 10, Swift 5, iOS 12

I've got two UILabel s in a horizontal StackView:

  • StackView: Alignment Fill & Distribution Fill
  • Label 1: No special constraints
  • Label 2: Proportional Width (half the size of Label 1)

Label 2 contains a word that's too long for the label size on an iPhone SE (smallest supported device), so I'm using an abbreviated version. On a bigger device, eg an iPad, I want to display the full word (should only be set once), so I tried this:

var label2set:Bool = false
print("label2: \(label2.frame.width)")

if !label2set && label2.frame.width > 100 && (UIApplication.shared.statusBarOrientation == .portrait || UIApplication.shared.statusBarOrientation == .portraitUpsideDown) {
    label2set = true
    label2.text = "VeryLongLabelText"
}

No matter if I use this code in viewDidLoad or viewWillAppear , the first time it's called the supposed label width is only about 70 (even on an iPad), even though it's clearly bigger in the simulator.

If I put the code in viewWillAppear and remove the check for label2set , then switch to the next view through my NavigationController and go back to my original one again, the code is called properly and the label displays the full text (width: about 200 on an iPad).

When do labels actually get set to their proper width, so when and how can I check the size?

If you really need such functionality why don't you just use idiom check and change label text itself?

if UIDevice.current.userInterfaceIdiom == .phone {
    // ...
} else {
    // ...
}

You can put your code inside viewDidLayoutSubviews method:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // do something...
}

EDIT:

viewDidLayoutSubviews will be called every time you have made changes to view controller's view or subviews... changes that concern view controller's view. I think in your case it's OK when it's called multiple times as when user rotates device you want to check if layout has changed in such a way that you now need to show shorter/longer text. Also when other view elements have autolayout constraints defined and you change something with them that may result your label to shrink/grow etc.

EDIT 2:

When using auto layout you basically can't know what size your label has ... when you check for width in tableViewCellForRowAt() you get with you used in story board or Nib file.

I suggest you just use two things for determining which version of text to use ... overall window width/height and current orientation (and width class if you support split view). In this case you know right before you set cell label which text you should set. You just have to decide if at current orientation and at overall width value, should you switch to shorter text.

Use stringsDict file for this. Create a stringsdict type file. follow this format:

<key>Login</key>
<dict>
    <key>NSStringVariableWidthRuleType</key>
    <dict>
        <key>100</key>
        <string>Login.</string>
        <key>200</key>
        <string>You must login before continuing.</string>
        <key>300</key>
        <string>Please enter your username and password to continue.</string>
    </dict>
</dict>

and later somewhere in code:

let localized = NSLocalizedString("Login", comment: "Prompt for user to log in.") as NSString

label.text = localized.variantFittingPresentationWidth(300)

NOTE: You can pass any integer you want into variantFittingPresentationWidth()

iOS will automatically resolve it to find the best match in your strings dictionary, counting downwards where necessary. For example, if you tried loading a string with width 500, the 300 string would be returned, but if you tried 299 then the 200 string would be returned.

Also extracting all strings from swift files into separated files like stringsdict is always best practice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM