Текст UISegmentedControl с несколькими строками?

Как сделать так, чтобы текст одной из кнопок в моем UISegmentedControl занимал несколько строк?


person Jason    schedule 10.04.2011    source источник
comment
Есть новости по вашей проблеме?   -  person Ahmad Kayyali    schedule 08.05.2011


Ответы (6)


Используйте UIAppearance, чтобы добиться цели. Приведенный ниже фрагмент кода будет работать. Вызовите это перед созданием сегмента.

Цель-C

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

Свифт

UILabel.appearanceWhenContainedInInstancesOfClasses([UISegmentedControl.self]).numberOfLines = 0
person Saranya Sivanandham    schedule 23.05.2015
comment
Поскольку кто-то проголосовал против: это не должно работать (numberOfLines даже не является селектором UIAppearance), но на самом деле это работает. Доказательство: i.stack.imgur.com/gE7Dv.png Похоже, проблема в том, что ширина метки, похоже, берется исключительно из первой строки. Вот почему я добавил эти пробелы в код. - person Matthias Bauch; 23.05.2015
comment
@MatthiasBauch попробуйте удалить символ новой строки - person Saranya Sivanandham; 23.05.2015
comment
Без новой строки это не было бы многострочным ярлыком. ;) В любом случае спасибо, но у меня больше нет этой проблемы, я недавно решил ее с помощью ответа, получившего наибольшее количество голосов. Просто хотел объяснить, что минусовать не нужно. - person Matthias Bauch; 23.05.2015
comment
Этот API доступен на iOS 9.0+. - person Yaroslav; 03.02.2016
comment
[[Внешний вид UILabelWhenContainedInInstancesOfClasses:@[[Класс UISegmentedControl]]] setNumberOfLines:0]; этот код будет работать для iOS 12 - person R. Mohan; 20.01.2019
comment
Swift 5 (добавьте в AppDelegate, чтобы это работало для элементов управления, добавленных в Storyboard): UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0 - person D. Pratt; 20.05.2019

Я сделал это следующим образом:

  • создать многострочный UILabel
  • заполнить метку N строками текста
  • преобразовать метку в UIImage
  • установить изображение как содержимое сегментов

Это работает гладко на iOS 4, 5, 6

Пример изображения iOS 5

и iOS 7 (просто удалите тень текста)

Пример изображения iOS 7

MultiLineSegmentedControl — файл заголовка

//
//  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 — файл реализации

//
//  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 — файл заголовка

//
//  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 — файл реализации

//
//  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

Используйте его так же, как обычный 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];

...
person Jenson    schedule 21.07.2011
comment
@SoButz: я не вижу субтитров. Я создал подкласс UISegmentedControl и добавил код выше. Создайте MultiLineSegmentedControl в viewDidLoad моего контроллера представления. Но он не показывает субтитры. У меня есть #import MultiLineSegmentedControl.h. Можешь мне помочь ? Спасибо - person iOSAppDev; 06.12.2012
comment
iOSAppDev, я обновил пример до метода, который сейчас использую в iOS 6. Попробуйте... - person Jenson; 12.12.2012
comment
@SoButz: у меня есть имена сегментов: @Все, @Мои\nДрузья, @Закрытие\nСкоро, @Рядом. Но все равно показывает не правильно. Посмотрите Что здесь не так? - person iOSAppDev; 16.01.2013
comment
m также имеет ту же проблему, что и указанная @iOSAppDev - person Harshit Gupta; 06.05.2014

Синтаксис Swift 3+ основан на ответе @Saranya Sivanandham

UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0
person Maverick    schedule 05.04.2017
comment
у меня это не работает :( кто-нибудь пробовал это и получил ожидаемый результат ?? - person Niib Fouda; 29.03.2018
comment
@Венкатеш Чеджария. Да, добавление этой строки в ваш делегат приложения или любой другой класс будет работать для UISegmentedControl, добавленного либо программно, либо из раскадровки. - person Maverick; 19.01.2019

Подход выше лучше, но ради альтернативы вы можете сделать что-то вроде:

for(UIView *subview in segmentedControl.subviews) {
        if([NSStringFromClass(subview.class) isEqualToString:@"UISegment"]) {
            for(UIView *segmentSubview in subview.subviews) {
                if([NSStringFromClass(segmentSubview.class) isEqualToString:@"UISegmentLabel"]) {
                    UILabel *label = (id)segmentSubview;
                    label.numberOfLines = 2;
                    label.text = @"Hello\nWorld";
                    CGRect frame = label.frame;
                    frame.size = label.superview.frame.size;
                    label.frame = frame;
                }
            }
        }
    }
person Snowman    schedule 12.11.2014
comment
Привет @moby, спасибо за альтернативу. если я хочу дать другое имя для текста моей метки, как я могу сделать это в вашем варианте? - person benhi; 09.12.2014

Лет спустя...

     for segment in segmented.subviews{
        for label in segment.subviews{
            if let labels = label as? UILabel{
                labels.numberOfLines = 2

            }
        }
    }
person Emilio Hoffmann    schedule 12.06.2017

Для iOS 12 приведенный ниже код будет работать как шарм.

    [[UILabel appearanceWhenContainedInInstancesOfClasses:@[[UISegmentedControl class]]] setNumberOfLines:0];
person R. Mohan    schedule 20.01.2019