2011-11-24 12 views
20

Mam pasek nawigacji z przyciskami po lewej i prawej stronie po obu stronach. Mam customTitlelabel, który ustawiam jako tytułView na UINavigationItem.UINavigationItem centrowanie tytułu

[self.navigationItem zestawTitleView: customTitleLabel];

Wszystko jest już w porządku. Problem, rozmiar rightbarButton jest dynamiczny w oparciu o dane wejściowe, które otrzymuję w jednym z pól tekstowych.

Dlatego tytuł jest automatycznie wycentrowany na podstawie dostępnego miejsca między przyciskami.

Jak ustawić tytuł na ustaloną pozycję?

Odpowiedz

15

Nie możesz zrobić bezpośrednio tego, co chcesz - pozycja twojego widoku tytułu jest poza twoją kontrolą (kiedy zarządza nim UINavigationBar).

Jednak istnieją co najmniej dwie strategie, aby uzyskać żądany efekt:

1) dodać widok tytuł nie jako „prawidłowe” TYTUŁ widokiem na pasku nawigacyjnym, ale jako podrzędny o UINavigationBar. (Uwaga: nie jest to "oficjalnie" usankcjonowane, ale widziałem, jak to się stało i działa.) Oczywiście musisz uważać na tytułową etykietę, zastępując bitów przycisków, i obsługiwać różne paski nav dla różnych orientacji itp. - trochę skrzypiący.)

2) Stwórz inteligentną podklasę UIView, która wyświetla dany widok podrzędny (który byłby twoim UILabel) na pozycji obliczonej tak, by skutecznie pokazać subview idealnie wyśrodkowany na ekranie. Aby to zrobić, twoja inteligentna podklasa UIView zareagowałaby na zdarzenia układu (lub zmiany właściwości frame) poprzez zmianę pozycji (frame) podeksportu etykiety.

Osobiście podoba mi się pomysł podejścia 2) najlepsze.

28

Ustawienie właściwości titleView paska nawigacji działa dobrze - nie ma potrzeby podklasy ani modyfikacji żadnych ram innych niż niestandardowe widoki.

Trick do coraz to skupione w stosunku do całkowitej szerokości UINavigationBar jest:

  1. ustawić szerokość widoku w zależności od rozmiaru tekstu
  2. ustawić wyrównanie do wyśrodkowany i
  3. ustaw maskę autouzupełniania, aby zmienić jej rozmiar na dostępne miejsce.

Oto przykład kodu, który tworzy niestandardowy tytułView z etykietą, która pozostaje wyśrodkowana w UINa vigationBar niezależnie od orientacji, szerokość paska po lewej lub prawej stronie:

+1

ja również pracować z dwóch linii tytuły ustawiające mniejszą czcionkę i numberOfLines = 2, gdy długość tytułu jest większa niż 25 znaków. W ten sposób masz wieloliniową etykietę tytułu. –

+1

Ponadto, zapomniałem powiedzieć, że w obliczeniu 'desiredWidth' kod powinien prawdopodobnie odwoływać się do' titleHeight' zamiast 'titleLabel.frame.size.height', który będzie zerowy ze względu na konstrukcję' CGRectZero'. –

+0

Świetna odpowiedź! Zaoszczędziłeś mnóstwo czasu – Julius

2

Próbowałem odpowiedzi aopsfana, ale nie zadziałało. Punkt przerwania ujawnił, że środek paska był "(480,0, 22,0)" (droga współrzędna X wyłączona).

Więc zmienił go w ten sposób:

- (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) 

} 

... i działa jak czar.Efekt przesuwania/zanikania podczas przesuwania kontrolerów widoku jest nienaruszony. (iOS 5.0)

0

Miałem podobną sytuację, gdy titleView powinien być wyśrodkowany w UINavigationBar. Lubię podejście occulus do podklasy UIView i przesłanianie setFrame:. Następnie mogę wyśrodkować ramkę wewnątrz wymiarów UINavigationBar.

W podklasie UIView:

-(void)setFrame:(CGRect)frame{ 
    super.frame = CGRectMake(320/2 - 50, 44/2 - 15, 100, 30); 
} 

UIView podklasy może być przypisane normalnie titleView dla każdego navigationItem. Deweloper nie musi programowo dodawać i usuwać specjalnych subviews z UINavigationBar.

3

Właściwa odpowiedź to zastąpienie sizeThatFits: niestandardowego titleView i zwrócenie jej rozmiaru zawartości. Pasek nawigacyjny wyśrodkowuje niestandardowy widok tytułowy, dopóki nie pozostało w nim miejsca.

Na przykład, jeśli masz UIView pojemnik UILabel Wewnątrz:

@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 
+0

Czy możesz wyjaśnić swoją odpowiedź? Zauważ, że pytanie dotyczy centrowania widoku tytułowego poziomo względem całej szerokości paska, a nie tylko w obrębie przydzielonego obszaru. – Ilya

11
override func viewDidLoad() { 
    super.viewDidLoad() 
    navigationController?.navigationBar.topItem?.title = "" 
} 

override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) 
    navigationItem.title = "Make peace soon" 
} 
+0

Czy naprawdę myślisz, że to rozwiązanie utrzyma tytuł przypięty do środka paska nawigacji pomimo szerokości lewego i prawego przycisku? –

+0

Nie mam pojęcia, dlaczego to działa ... ale tak jest! Jeśli ktokolwiek mógłby wyjaśnić dlaczego, byłby to docenione. – th3hamburgler

+0

Myślę, że ma to związek z cyklem życia widoku. viewDidLoad jest wywoływany przed viewWillLayout, więc w zasadzie tworzy pusty ciąg, który nie zajmuje żadnych rozmiarów. Kiedy wywoływana jest viewWillLayout, rozmiar tytułu jest prawie zerowy. Następnie w viewWillAppear, która dzieje się PO układ jest gotowy, dodaje to, czego naprawdę chce. Po tym nie następuje przeniesienie. –

1

miałem podobny problem. enter image description here Moje rozwiązanie to ukryj oryginalny przycisk Wstecz, dodaj własną implementację. Ponieważ system zarezerwuje miejsce dla pozostawionych przedmiotów.

UIImage* cancelIcon = [UIImage imageNamed:@"ic_clear"]; 
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] initWithImage:cancelIcon style:UIBarButtonItemStylePlain target:self action:@selector(back:)]; 

i selektor jest prosta

- (void)back:(UIButton *) sender 
{ 
    [self.navigationController popViewControllerAnimated:YES]; 
} 

teraz wygląda to tak: enter image description here

oh ... i nie zapomnij użyć autolayout w niestandardowym tytułowej podgląd Jeśli mieć zawartość o dynamicznej długości, taką jak etykieta. Dodam dodatkowy układ w CustomView dać to jak „wrap_content” w Androidzie, ustawiając go wyśrodkowany do rodzica, a początkowe i końcowe przestrzeń „> =” 0

enter image description here

Powiązane problemy