UISegmentedControl text with multiple lines?
Use UIAppearance to get things done. The below code snippet will work. Call this before creating your segment.
Objective-C
[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];
Swift
UILabel.appearanceWhenContainedInInstancesOfClasses([UISegmentedControl.self]).numberOfLines = 0
I did it this way:
- create a multiline UILabel
- fill the label with N lines of text
- convert the label into an UIImage
- set the image as a segments content
This works smooth on iOS 4, 5, 6
and iOS 7 (just remove the text shadow)
MultiLineSegmentedControl - header file
//// MultiLineSegmentedControl.h//// Created by Jens Kreiensiek on 20.07.11.// Copyright 2011 SoButz. All rights reserved.//#import <Foundation/Foundation.h>@interface MultiLineSegmentedControl : UISegmentedControl- (void)setMultilineTitle:(NSString *)title forSegmentAtIndex:(NSUInteger)segment;@end
MultiLineSegmentedControl - implementation file
//// MultiLineSegmentedControl.m//// Created by Jens Kreiensiek on 20.07.11.// Copyright 2011 SoButz. All rights reserved.//#import "MultiLineSegmentedControl.h"#import "UIView+LayerShot.h"@interface MultiLineSegmentedControl()@property (nonatomic, retain) UILabel *theLabel;@end@implementation MultiLineSegmentedControl@synthesize theLabel;- (void)dealloc{ self.theLabel = nil; [super dealloc];}- (UILabel *)theLabel{ if (!self->theLabel) { self->theLabel = [[UILabel alloc] initWithFrame:CGRectZero]; self->theLabel.textColor = [UIColor whiteColor]; self->theLabel.backgroundColor = [UIColor clearColor]; self->theLabel.font = [UIFont boldSystemFontOfSize:13]; self->theLabel.textAlignment = UITextAlignmentCenter; self->theLabel.lineBreakMode = UILineBreakModeWordWrap; self->theLabel.shadowColor = [UIColor darkGrayColor]; self->theLabel.numberOfLines = 0; } return self->theLabel;}- (void)setMultilineTitle:(NSString *)title forSegmentAtIndex:(NSUInteger)segment{ self.theLabel.text = title; [self.theLabel sizeToFit]; [self setImage:self.theLabel.imageFromLayer forSegmentAtIndex:segment];}@end
UIView+LayerShot - header file
//// UIView+LayerShot.h//// Created by Jens Kreiensiek on 29.06.12.// Copyright (c) 2012 SoButz. All rights reserved.//#import <UIKit/UIKit.h>@interface UIView (LayerShot)- (UIImage *)imageFromLayer;@end
UIView+LayerShot - implementation file
//// UIView+LayerShot.m//// Created by Jens Kreiensiek on 29.06.12.// Copyright (c) 2012 SoButz. All rights reserved.//#import "UIView+LayerShot.h"#import <QuartzCore/QuartzCore.h>@implementation UIView (LayerShot)- (UIImage *)imageFromLayer{ UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0); [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image;}@end
Use it just like a normal UISegmentedControl:
...MultiLineSegmentedControl *segment = [[MultiLineSegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"A", @"B", nil]];segment.segmentedControlStyle = UISegmentedControlStyleBar;segment.frame = CGRectMake(0, 0, 200, segment.frame.size.height * 1.5);[segment setMultilineTitle:@"Title A\nSubtitle A" forSegmentAtIndex:0];[segment setMultilineTitle:@"Title B\nSubtitle B" forSegmentAtIndex:1];[self.view addSubview:segment];[segment release];...
Swift 3+ syntax based on answer by @Saranya Sivanandham
UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0