Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resize text (font) to fit in UISegment of UISegmentedControl?

Is there any way to reduce font size that can be fit in single segment of UISegmentedControl ?

Have tried many thing something like,

[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] adjustsFontSizeToFitWidth];

[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setMinimumScaleFactor:0.5];

AND

 NSArray *arr = segment.subviews;  // segment is UISegmentedControl object

for (int i = 0; i < arr.count; i++) {

    UIView *aSegment = [arr objectAtIndex:i];

    for (UILabel *label in aSegment.subviews) {

        if ([label isKindOfClass:[UILabel class]]) {

            UILabel *myLabel = (UILabel *)label;

            [myLabel setNumberOfLines:0];

            label.numberOfLines = 0;
            label.adjustsFontSizeToFitWidth = YES;
            label.minimumScaleFactor = 0.5;
        }



    }
}

able to set number of lines of label of segment like,

  [[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];

Can set single segment size as per content like,

  segment.apportionsSegmentWidthsByContent = YES;

but every segment has different size in this case.

I want to keep same size of every segment and want to reduce font size that can be fit in UISegmentLabel (label) of UISegmentedControl something like minimumscalefactor or minimumfontsize or adjustsFontSizeToFitWidth. These properties is not working for label when contains in UISegmentedControl.

If any one can help to achieve this, it will be appreciated!!

Thanks in advance!!

like image 419
Ketan Parmar Avatar asked Jul 22 '16 07:07

Ketan Parmar


3 Answers

I found the issue, Actually it was my mistake!!! I was setting numberOfLines,adjustsFontSizeToFitWidth,minimumScaleFactor and TitleTextAttributes toghether. If we set titleTextAttribute then minimumScaleFactor can't work.

Update : (As asked by @HawkEye1194 in comment of another answer)

I have end up with below solution,

 //this will allow multiple lines in label contained by every segment in segmentedcontroller

[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];


UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:option];
segment.frame = CGRectMake(20, 50, self.view.frame.size.width - 40, 50);
segment.tintColor = [UIColor grayColor];
segment.selectedSegmentIndex = 0;
segment.backgroundColor = [UIColor whiteColor];
segment.tag = segmentedControllerBaseTag;


[segment addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];

[segment setTitleTextAttributes:@{NSFontAttributeName :[UIFont fontWithName:@"HelveticaNeue" size:17.0], NSForegroundColorAttributeName : [UIColor darkGrayColor] } forState:UIControlStateNormal];
[segment setTitleTextAttributes:@{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue" size:17.0],NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];

If your not setting title textattribute as above then you can use below code

// ********** if titletextattributes are not set then below method works ***********

   for(uint i=0;i<[segment subviews].count;i++)
   {
    for(UIView *view in [[[segment subviews] objectAtIndex:i] subviews])
    {
        if([view isKindOfClass:[UILabel class]])
        {

            [(UILabel*)view setNumberOfLines:0];
            [(UILabel*)view setAdjustsFontSizeToFitWidth:YES];
            [(UILabel*)view setMinimumScaleFactor:0.7];


        }
    }
}

You can adjust single segment's size as per it's content by below code,

 //*************** adjust single segment size as per content

 segment.apportionsSegmentWidthsByContent = YES;
like image 144
Ketan Parmar Avatar answered Oct 12 '22 11:10

Ketan Parmar


Try this, I hope this will help you and you will get an idea how this works-

I have a UISegmentedControl i.e. _userProfileSagmentOutlet having three segments. Here is sample code-

CGFloat fontSize = 15;

[_userProfileSagmentOutlet setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Roboto-medium" size:fontSize],
                                                    NSForegroundColorAttributeName:[UIColor whiteColor]}
                                         forState:UIControlStateSelected];

[_userProfileSagmentOutlet setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Roboto-medium" size:fontSize],
                                                    NSForegroundColorAttributeName:[UIColor whiteColor]}
                                         forState:UIControlStateNormal];

this is the previous code which truncate tail of title like below image-

enter image description here

here is the main logic which fit each title in segments with same font size-

CGFloat fontSize = 15;

NSAttributedString* firstTitle = [[NSAttributedString alloc] initWithString:@"Membership History" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Roboto-medium" size:fontSize]}];

NSAttributedString* secondTitle = [[NSAttributedString alloc] initWithString:@"Event History" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Roboto-medium" size:fontSize]}];

NSAttributedString* thirdTitle = [[NSAttributedString alloc] initWithString:@"Booked Classes" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Roboto-medium" size:fontSize]}];


float maxW=MAX(MAX(firstTitle.size.width, secondTitle.size.width), thirdTitle.size.width);

while (maxW > _userProfileSagmentOutlet.subviews[0].frame.size.width) {

    fontSize--;

    firstTitle = [[NSAttributedString alloc] initWithString:@"Membership History" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Roboto-medium" size:fontSize]}];

    secondTitle = [[NSAttributedString alloc] initWithString:@"Event History" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Roboto-medium" size:fontSize]}];

    thirdTitle = [[NSAttributedString alloc] initWithString:@"Booked Classes" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Roboto-medium" size:fontSize]}];

    maxW=MAX(MAX(firstTitle.size.width, secondTitle.size.width), thirdTitle.size.width);


}
[_userProfileSagmentOutlet setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Roboto-medium" size:fontSize],
                                                    NSForegroundColorAttributeName:[UIColor whiteColor]}
                                         forState:UIControlStateSelected];

[_userProfileSagmentOutlet setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Roboto-medium" size:fontSize],
                                                    NSForegroundColorAttributeName:[UIColor whiteColor]}
                                         forState:UIControlStateNormal];

after using this code image look like this(same font size and text fit to segment and works fine)-

enter image description here

Here is Swift extension if someone needed-

    var fontSize:CGFloat = 15.0;

    var firstTitle = NSMutableAttributedString.init(string: "Membership History", attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)])

    var secondTitle = NSMutableAttributedString.init(string: "Events History" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);

    var thirdTitle = NSMutableAttributedString.init(string: "Booked Classes" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);

    var maxW:CGFloat = max(max(firstTitle.size().width, secondTitle.size().width), thirdTitle.size().width);

    while (maxW > userProfileSagmentOutlet.subviews[0].frame.size.width) {

        fontSize--;

         firstTitle = NSMutableAttributedString.init(string: "Membership History", attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)])

         secondTitle = NSMutableAttributedString.init(string: "Events History" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);

         thirdTitle = NSMutableAttributedString.init(string: "Booked Classes" ,attributes:[NSFontAttributeName: UIFont.systemFontOfSize(fontSize)]);

         maxW = max(max(firstTitle.size().width, secondTitle.size().width), thirdTitle.size().width);

    }
    userProfileSagmentOutlet.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(fontSize),NSForegroundColorAttributeName:UIColor.whiteColor()], forState:UIControlState.Normal)

    userProfileSagmentOutlet.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFontOfSize(fontSize),NSForegroundColorAttributeName:UIColor.whiteColor()], forState:UIControlState.Selected)
like image 21
Rohit Khandelwal Avatar answered Oct 12 '22 11:10

Rohit Khandelwal


SWIFT 4

allow multiple lines in label

if #available(iOS 9.0, *) {
    UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0
}
like image 29
Ted Avatar answered Oct 12 '22 11:10

Ted