UINavigationBar многострочный заголовок - PullRequest
54 голосов
/ 11 марта 2010

Есть ли простой способ переопределить titleView текущего элемента панели навигации на панели навигации в контроллере навигации? Я попытался создать новый UIView и заменить свойство titleView topView своим собственным UIVIew безуспешно.

По сути, я хочу многострочный заголовок для заголовка панели навигации. Есть предложения?

Ответы [ 9 ]

83 голосов
/ 12 апреля 2010

Установите titleView свойство UINavigationItem. Например, в методе viewDidLoad контроллера представления вы можете сделать что-то вроде:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 480, 44)];
label.backgroundColor = [UIColor clearColor];
label.numberOfLines = 2;
label.font = [UIFont boldSystemFontOfSize: 14.0f];
label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.text = @"This is a\nmultiline string";

self.navigationItem.titleView = label;

#if !__has_feature(objc_arc)
[label release];
#endif

Это выглядит так:

multi-line titlebar label

Помните, что свойство titleView равно , игнорируется , если leftBarButtonItem не равно nil.

24 голосов
/ 20 сентября 2015

для Swift:

let label = UILabel(frame: CGRectMake(0, 0, UIScreen.main.bounds.width, 44))
label.backgroundColor = UIColor.clearColor()
label.numberOfLines = 0
label.textAlignment = NSTextAlignment.Center
label.text = "multiline string"
self.navigationItem.titleView = label

для swift 4:

    let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 44.0))
    label.backgroundColor = UIColor.clear
    label.numberOfLines = 0
    label.textAlignment = NSTextAlignment.center
    label.text = "first line\nsecond line"
    self.navigationItem.titleView = label   
23 голосов
/ 10 октября 2016

Быстрое решение:

2 строки в NavigationBar:

private func setupTitleView() {
    let topText = NSLocalizedString("key", comment: "")
    let bottomText = NSLocalizedString("key", comment: "")

    let titleParameters = [NSForegroundColorAttributeName : UIColor.<Color>(),
                           NSFontAttributeName : UIFont.<Font>]
    let subtitleParameters = [NSForegroundColorAttributeName : UIColor.<Color>(),
                              NSFontAttributeName : UIFont.<Font>]

    let title:NSMutableAttributedString = NSMutableAttributedString(string: topText, attributes: titleParameters)
    let subtitle:NSAttributedString = NSAttributedString(string: bottomText, attributes: subtitleParameters)

    title.appendAttributedString(NSAttributedString(string: "\n"))
    title.appendAttributedString(subtitle)

    let size = title.size()

    let width = size.width
    guard let height = navigationController?.navigationBar.frame.size.height else {return}

    let titleLabel = UILabel(frame: CGRectMake(0,0, width, height))
    titleLabel.attributedText = title
    titleLabel.numberOfLines = 0
    titleLabel.textAlignment = .Center

    navigationItem.titleView = titleLabel
}

2 строки в BarButton

    let string = NSLocalizedString("key", comment: "")
    let attributes = [NSForegroundColorAttributeName : UIColor.<Color>,
                      NSFontAttributeName : UIFont.<Font>]
    let size = (string as NSString).sizeWithAttributes(attributes)
    guard let height = navigationController?.navigationBar.frame.size.height else {return}
    let button:UIButton = UIButton(frame: CGRectMake(0, 0, size.width, height))
    button.setAttributedTitle(NSAttributedString(string: string, attributes: attributes), forState: .Normal)
    button.addTarget(self, action: #selector(<SELECTOR>), forControlEvents: .TouchUpInside)
    button.titleLabel?.numberOfLines = 0
    button.titleLabel?.textAlignment = .Right
    let rightBarButton = UIBarButtonItem(customView: button)
    navigationItem.rightBarButtonItem = rightBarButton

результат -

enter image description here

6 голосов
/ 30 ноября 2015

После долгих изменений я так и не смог заставить работать решение petert для меня в iOS 8. Вот решение с возможностью копирования и вставки для iOS 8/9. Кредит идет на пост Мэтта Кертиса на github

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if(!self.navigationItem.titleView){
        self.navigationItem.titleView = ({
            UILabel *titleView = [UILabel new];
            titleView.numberOfLines = 0;
            titleView.textAlignment = NSTextAlignmentCenter;
            titleView.attributedText = [[NSAttributedString alloc] initWithString:@"2\nLINES" attributes:
                self.navigationController.navigationBar.titleTextAttributes
            ];

            [titleView sizeToFit];
            // You'll need to set your frame otherwise if your line breaks aren't explcit.

            titleView;
        });
    }
}
4 голосов
/ 06 апреля 2017

Что делать, если этикетка не отцентрирована

Если вы столкнулись с той же проблемой, что и я - этот ярлык не центрирован в навигационном элементе из-за кнопки назад, вставьте вашу UILabel в UIView. UILabel тогда не будет вынужден расти вместе со своим текстом, но прекратит расти, когда его ширина увеличит ширину представления. Подробнее об этой проблеме вы можете найти здесь: Невозможно установить titleView в центре панели навигации, потому что кнопка возврата (ответ Даррена)

Не центрировано:

enter image description here

- (void)setTwoLineTitle:(NSString *)titleText color:(UIColor *)color font:(UIFont *)font {
    CGFloat titleLabelWidth = [UIScreen mainScreen].bounds.size.width/2;

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, titleLabelWidth, 44)];
    label.backgroundColor = [UIColor clearColor];
    label.numberOfLines = 2;
    label.font = font;
    label.adjustsFontSizeToFitWidth = YES;
    label.textAlignment = UITextAlignmentCenter;
    label.textColor = color;
    label.text = titleText;

    self.navigationItem.titleView = label;
}

Сосредоточенный:

enter image description here

- (void)setTwoLineTitle:(NSString *)titleText color:(UIColor *)color font:(UIFont *)font {
    CGFloat titleLabelWidth = [UIScreen mainScreen].bounds.size.width/2;

    UIView *wrapperView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, titleLabelWidth, 44)];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, titleLabelWidth, 44)];
    label.backgroundColor = [UIColor clearColor];
    label.numberOfLines = 2;
    label.font = font;
    label.adjustsFontSizeToFitWidth = YES;
    label.textAlignment = UITextAlignmentCenter;
    label.textColor = color;
    label.text = titleText;

    [wrapperView addSubview:label];

    self.navigationItem.titleView = wrapperView;
}
3 голосов
/ 16 марта 2018

Вот способ Swift 4 -

let upperTitle = NSMutableAttributedString(string: "\(text1)", attributes: [NSAttributedStringKey.font: UIFont(name: "SFProDisplay-Heavy", size: 17)!])
let lowerTitle = NSMutableAttributedString(string: "\n\((text2)!)", attributes: [NSAttributedStringKey.font: UIFont(name: "SFProText-Light", size: 11)! , NSAttributedStringKey.foregroundColor: UIColor(hex: "#607D8B")])

upperTitle.append(lowerTitle)

let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 400, height:44))
label1.numberOfLines = 0
label1.textAlignment = .center
label1.attributedText = upperTitle  //assign it to attributedText instead of text
self.navigationItem.titleView = label1
3 голосов
/ 21 июня 2017

Вот Swift 3 версия обработки многострочного заголовка:

override func viewDidLoad() {
    super.viewDidLoad()

    let label = UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
    label.backgroundColor = .clear
    label.numberOfLines = 0
    label.textAlignment = .center
    label.font = UIFont.boldSystemFont(ofSize: 14.0)
    label.text = "This is a Multi-Line title of UINavigationBar"
    self.navigationItem.titleView = label
}
2 голосов
/ 16 августа 2018

Swift 4

extension UINavigationItem {
    @objc func setTwoLineTitle(lineOne: String, lineTwo: String) {
        let titleParameters = [NSAttributedStringKey.foregroundColor : UIColor.white,
                               NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 17)] as [NSAttributedStringKey : Any]
        let subtitleParameters = [NSAttributedStringKey.foregroundColor : UIColor.flatWhite(),
                                  NSAttributedStringKey.font : UIFont.systemFont(ofSize: 12)] as [NSAttributedStringKey : Any]

        let title:NSMutableAttributedString = NSMutableAttributedString(string: lineOne, attributes: titleParameters)
        let subtitle:NSAttributedString = NSAttributedString(string: lineTwo, attributes: subtitleParameters)

        title.append(NSAttributedString(string: "\n"))
        title.append(subtitle)

        let size = title.size()

        let width = size.width
        let height = CGFloat(44)

        let titleLabel = UILabel(frame: CGRect.init(x: 0, y: 0, width: width, height: height))
        titleLabel.attributedText = title
        titleLabel.numberOfLines = 0
        titleLabel.textAlignment = .center

        titleView = titleLabel
    }
}

Здесь жестко заданы шрифт, цвет и высота панели навигации.

1 голос
/ 27 марта 2018

Большинство решений, за исключением одного из @gbk, используют жестко заданную высоту 44pt для UIView (вид оболочки) и UILabel. Все созданы по кодам. Я упустил из виду решение @gbk, которое динамически считывает высоту панели навигации.

Я столкнулся с проблемой, когда orientation = landscape на iOS 11 (iPhone 5s). Высота надписи не будет изменяться, и когда я устанавливаю одну строку текста для альбомной ориентации, текст выравнивается по нижней части панели навигации.

Каким-то образом я обнаружил, что могу добавить UILabel в раскадровку и создать для этого IBOutlet. Разве это не лучше?

  1. Добавление UIView на панель навигации в раскадровке. При перетаскивании его на панель навигации оно отображается в виде синего поля. Если появляется вертикальный штрих, вы добавляете его в массив элементов кнопок левой / правой панели. Примечание: может быть только ONE UIView. Если вы добавите его правильно, он появится под Navigation Item на панели сцены (слева).
  2. Перетащите UILabel в этот UIView. enter image description here
  3. Так как UIView будет иметь NO SIZE , но централизован на панели навигации, вы не можете добавить ограничение в четыре нуля. Просто добавьте два ограничения к UILabel, чтобы оно располагалось в центре суперпредставления: выровняйте Center X и Y по Superview.
  4. Настройте UILabel как обычно. Для нескольких строк я устанавливаю количество строк равным нулю (0).
  5. Создайте IBOutlet на вашем контроллере представления, и вы можете использовать его как обычно. Чтобы иметь другой размер текста, используйте строку атрибута (множество решений выше).

Я тестировал на iPhone 5s с iOS 11.2.6, и текст без проблем помещается по центру, отлично работает на портретной и альбомной ориентациях.

...