12

I have a relative longer text items in my segmented control so I need to break text at certain points. Is it possible to use line breaks? I know at buttons I need to set line break to word wrap, but how to to set it for UISegmentedControl.

Niib Fouda
  • 1,383
  • 1
  • 16
  • 21
János
  • 32,867
  • 38
  • 193
  • 353

5 Answers5

51

Please refer to this answer

Swift 3+

UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0

Objective C

[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];
Maverick
  • 3,209
  • 1
  • 34
  • 40
4

if you have a standard UISegmentedControl you can use the following idea:

[_segmentedControl.subviews enumerateObjectsUsingBlock:^(UIView * obj, NSUInteger idx, BOOL *stop) {
    [obj.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[UILabel class]]) {
            UILabel *_tempLabel = (UILabel *)obj;
            [_tempLabel setNumberOfLines:0];
        }
    }];     
}];

you may need to set the height of your instance as well.


NOTE: I need to add a little warning about – as rmaddy has also pointed out correctly – this is a quite fragile solution, because if the segmented control's view hierarchy would be changed in the future iOS versions that code may not work properly anymore.

holex
  • 23,961
  • 7
  • 62
  • 76
  • There's no need for the 1st `if` statement. All subviews, by definition, must be `UIView` instances. It should be noted that solutions like this are fragile. While this code does proper checking to avoid crashes, it could easily stop working during an iOS update if Apple changes the internal view hierarchy of the segmented control. – rmaddy Jan 19 '15 at 16:28
  • yes, unfortunately that is quite fragile from that point of view what you have pointed. I think I just added the 1st `if` statement because of routine... it won't hurt, but – as you said – it is completely useless. – holex Jan 19 '15 at 16:33
2

Swift 4 version of solution. segmentedControl is your instance of UISegmentedControl.

        for segmentItem : UIView in segmentedControl.subviews
    {
        for item : Any in segmentItem.subviews {
            if let i = item as? UILabel {
                i.numberOfLines = 0
                // change other parameters: color, font, height ... 
            }
        }
    }

Don't forget to set segmentedControl's height as a doubled font's height.

Agisight
  • 1,778
  • 1
  • 14
  • 15
1

Add [yourSegmentedControl layoutIfNeeded]; method, before adding it as a subview. Then iterate all the SegmentedControl subviews and modify the numberOfLines property of the title label.

Here is the code

for (id segmentItem in [yourSegmentedControl subviews])
{
  if ([segmentItem isKindOfClass:[UILabel class]])
   {
     UILabel *titleLabel = (UILabel *) segmentItem;
     titleLabel.frame = CGRectMake(0, 0, 100, 50); //modify the frame if the second line is not showing.
     titleLabel.numberOfLines = 0;
   }
}
Shamsudheen TK
  • 30,739
  • 9
  • 69
  • 102
0

I changed little bit the code from this link, and here is Swift extension:

extension UISegmentedControl {

  func makeTitleMultiline(){
    for i in 0...self.numberOfSegments - 1 {
      let label = UILabel(frame: CGRect(x: 0, y: -7, width: (self.frame.width-10)/CGFloat(self.numberOfSegments), height: self.frame.height))
      label.textColor = i == 0 ? UIColor.red : UIColor.blue
      label.text = self.titleForSegment(at: i)
      label.numberOfLines = 0
      label.textAlignment = .center
      label.adjustsFontSizeToFitWidth = true
      label.tag = i
      self.setTitle("", forSegmentAt: i)
      self.subviews[i].addSubview(label)
    }
  }

  func setSelectedTitleColor() {
    for i in 0...self.numberOfSegments - 1 {
      let label = self.subviews[self.numberOfSegments - 1 - i].subviews[1] as? UILabel
      label?.textColor = label?.tag == self.selectedSegmentIndex ? UIColor.red : UIColor.blue
    }
  }
}
Niib Fouda
  • 1,383
  • 1
  • 16
  • 21