UINavigationItem, центрирующий название
У меня есть панель навигации с левой и правой клавишами на каждой стороне. У меня есть customTitlelabel
, который я задал как titleView UINavigationItem
.
[self.navigationItem setTitleView: customTitleLabel];
Теперь все в порядке. Проблема в том, что размер правой панели является динамическим на основе ввода, который я получаю в одном из текстовых полей.
Поэтому заголовок автоматически центрируется на основе доступного пространства между кнопками.
Как я могу установить заголовок на фиксированную позицию?
Ответы
Ответ 1
Вы не можете делать то, что хотите напрямую - позиция вашего заголовка не соответствует вашему управлению (когда управляется UINavigationBar
).
Однако для получения желаемого эффекта есть как минимум две стратегии:
1) Добавьте название заголовка не как "правильное" название заголовка панели навигации, а как подпункт UINavigationBar
. (Обратите внимание: это не "официально" санкционировано, но я видел, как это делается и работает. Очевидно, вам нужно следить за тем, чтобы ваш ярлык названия переписывал биты кнопок и обрабатывал различные бары на разных уровнях для разных ориентаций и т.д. - немного странно.)
2) Создайте интеллектуальный подкласс UIView, который отобразит данный подъярус (который будет вашим UILabel) в позиции, рассчитанной так, чтобы эффективно отображать подвью, идеально расположенную на экране. Чтобы сделать это, ваш интеллектуальный подкласс UIView будет реагировать на события макета (или изменения свойств t22 и т.д.), Изменив положение (frame
) подвью. Label.
Лично мне нравится идея подхода 2) лучшая.
Ответ 2
Настройка свойства titleView на панели навигации работает просто отлично - не нужно подклассифицировать или изменять любые кадры, отличные от настроек вашего пользовательского представления.
Трюк для его центрирования относительно общей ширины UINavigationBar заключается в следующем:
- установите ширину вашего представления в соответствии с размером текста
- установите выравнивание по центру и
- установите маску авторазмера, чтобы она была изменена до доступного пространства.
Вот пример кода, который создает пользовательский заголовок с ярлыком, который остается центрированным в UINavigationBar независимо от ориентации, ширины влево или вправо:
self.title = @"My Centered Nav Title";
// Init views with rects with height and y pos
CGFloat titleHeight = self.navigationController.navigationBar.frame.size.height;
UIView *titleView = [[UIView alloc] initWithFrame:CGRectZero];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
// Set font for sizing width
titleLabel.font = [UIFont boldSystemFontOfSize:20.f];
// Set the width of the views according to the text size
CGFloat desiredWidth = [self.title sizeWithFont:titleLabel.font
constrainedToSize:CGSizeMake([[UIScreen mainScreen] applicationFrame].size.width, titleLabel.frame.size.height)
lineBreakMode:UILineBreakModeCharacterWrap].width;
CGRect frame;
frame = titleLabel.frame;
frame.size.height = titleHeight;
frame.size.width = desiredWidth;
titleLabel.frame = frame;
frame = titleView.frame;
frame.size.height = titleHeight;
frame.size.width = desiredWidth;
titleView.frame = frame;
// Ensure text is on one line, centered and truncates if the bounds are restricted
titleLabel.numberOfLines = 1;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
titleLabel.textAlignment = NSTextAlignmentCenter;
// Use autoresizing to restrict the bounds to the area that the titleview allows
titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
titleView.autoresizesSubviews = YES;
titleLabel.autoresizingMask = titleView.autoresizingMask;
// Set the text
titleLabel.text = self.title;
// Add as the nav bar titleview
[titleView addSubview:titleLabel];
self.navigationItem.titleView = titleView;
Ответ 3
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.topItem?.title = ""
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationItem.title = "Make peace soon"
}
Ответ 4
Правильный ответ - переопределить sizeThatFits:
вашего пользовательского titleView
и вернуть его размер содержимого. Навигационная панель центрирует пользовательский заголовок, пока не останется свободного места.
Например, если у вас есть контейнер UIView
с UILabel
внутри:
@interface CustomTitleView : UIView
@property UILabel* textLabel;
@end
@implementation CustomTitleView
- (CGSize)sizeThatFits:(CGSize)size {
CGSize textSize = [self.textLabel sizeThatFits:size];
CGSize contentSize = size;
contentSize.width = MIN( size.width, textSize.width );
return contentSize;
}
@end
Ответ 5
Я попытался ответить aopsfan, но это не сработало. Точка останова показала, что центр бара был "(480,0, 22,0)" (координата X отсутствует).
Поэтому я изменил его на следующее:
- (void)layoutSubviews
{
[super layoutSubviews];
// Center Title View
UINavigationItem* item = [self topItem]; // (Current navigation item)
[item.titleView setCenter:CGPointMake(160.0, 22.0)];
// (...Hard-coded; Assuming portrait iPhone/iPod touch)
}
... и он работает как шарм. Эффект слайда/затухания при нажатии на контроллеры просмотра не поврежден. (iOS 5.0)
Ответ 6
У меня была аналогичная проблема.
Мое решение - скрыть исходную кнопку "Назад", добавить добавить свою собственную реализацию. Поскольку система зарезервирует место для левых элементов.
UIImage* cancelIcon = [UIImage imageNamed:@"ic_clear"];
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] initWithImage:cancelIcon style:UIBarButtonItemStylePlain target:self action:@selector(back:)];
и селектор прост
- (void)back:(UIButton *) sender
{
[self.navigationController popViewControllerAnimated:YES];
}
теперь он выглядит так:
![введите описание изображения здесь]()
oh... и не забудьте использовать автозапуск в своем пользовательском заголовке, если в нем есть динамическое содержимое длины, такое как метка. Я добавляю дополнительный макет в пользовательское представление, чтобы дать ему как "wrap_content" в Android, установив его в центре на родительский, а ведущее и конечное пространство " > =" 0
![введите описание изображения здесь]()
Ответ 7
У меня была аналогичная ситуация, когда a titleView
должен быть сосредоточен в UINavigationBar. Мне нравится окклюзионный подход подкласса UIView и переопределение setFrame:
. Затем я могу центрировать рамку внутри размеров UINavigationBar.
В подклассе UIView:
-(void)setFrame:(CGRect)frame{
super.frame = CGRectMake(320 / 2 - 50, 44 / 2 - 15, 100, 30);
}
Подкласс UIView можно затем назначить обычно titleView
для каждого элемента навигации. Разработчику не нужно программно добавлять и удалять специальные подпрограммы из UINavigationBar.