2017-06-29 30 views
28

Zbudowałem swoją aplikację przy użyciu nowej wersji beta Xcode 9 dla ios 11. Znalazłem problem z UITabBar, gdzie elementy są rozłożone przez UITabBar, a tytuł jest wyrównany do obrazu. Próbowałem zmienić kod, aby działało, ale nadal nie udało się.ios 11 UITabBar UITabBar Problem z pozycjonowaniem

ios 10+

enter image description here

ios 11

enter image description here

mogę zmienić pozycję tytułu korzystania tabBarItem.titlePositionAdjustment Ale to nie jest mój wymóg powinien automatycznie się ryczeć sam obraz. Próbowałem ustawić tabbar.itemPositioning to UITabBarItemPositioningCentered, a także próbowałem zmienić itemSpacing i width, ale nadal nie działało. Czy ktoś może mi pomóc zrozumieć, dlaczego tak się dzieje i jak to naprawić? Chcę, żeby polubił wersję ios 10+, a zdjęcia są robione z lewego rogu iPada.

+7

To funkcja, a nie błąd. – matt

+0

Nie jest to tylko kwestia obiektywu c, ale ogólnie rzecz biorąc, zastosowanie obiektywne i szybkie. – Jeet

+0

Funkcja? idk. Bardziej przypadek Apple "ulepszający" coś bez myślenia przez wszystkie konsekwencje. –

Odpowiedz

27

Utrzymuję dużą aplikację na iPada napisaną głównie w Objective-C, która przetrwała kilka wersji iOS. Natknąłem się na sytuację, w której potrzebowałem wyglądu paska zakładek przed iOS 11 (z ikonami nad tytułami zamiast obok nich) dla pasków z dwoma zakładkami. Moim rozwiązaniem było stworzenie podklasy UITabBar, która nadpisuje metodę traitCollection, tak aby zawsze zwracała poziomo-kompaktową kolekcję cech. Powoduje to, że iOS 11 wyświetla tytuły pod ikonami dla wszystkich przycisków paska kart.

Aby tego użyć, należy ustawić niestandardową klasę pasków kart w serii ujęć do tej nowej podklasy i zmienić dowolne wyjścia w kodzie wskazujące paski kart tego nowego typu (nie zapomnij o tym zaimportuj plik nagłówkowy poniżej).

plik .h jest prawie pusty w tym przypadku:

// 
// MyTabBar.h 
// 

#import <UIKit/UIKit.h> 

@interface MyTabBar : UITabBar 

@end 

Oto.Plik m przy realizacji sposobu traitCollection:

// 
// MyTabBar.m 
// 

#import "MyTabBar.h" 

@implementation MyTabBar 

// In iOS 11, UITabBarItem's have the title to the right of the icon in horizontally regular environments 
// (i.e. the iPad). In order to keep the title below the icon, it was necessary to subclass UITabBar and override 
// traitCollection to make it horizontally compact. 

- (UITraitCollection *)traitCollection { 
    return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; 
} 

@end 
+1

Nie używam storyboardu/IB, ale udało mi się uzyskać ten sam efekt przez podklasy UITabBarController zamiast UITabBar i nadpisanie tej samej metody traitCollection. – massimobio

+0

Nie tylko! Działa również z storyboardem/IB, który używa podklas UITabBarController z tą poprawką ... –

+2

Właściwie to zadrap. Podklasowanie UITabBarController nie jest zalecane i w rzeczywistości pasek nawigacyjny zepsuł się z iOS 11 GM podczas tego. – massimobio

10

UWAGA: This fix above wydaje się działać całkiem ładnie. Nie wiem, jak to będzie działać w przyszłości, ale na razie działa całkiem dobrze.


Według this WWDC talk, jest to nowe zachowanie dla:

  • iPhone w krajobraz
  • iPad cały czas

A jeśli mam poprawnie czytać, to zachowanie nie można zmienić:

Mamy zupełnie nowy wygląd paska zakładek, zarówno w krajobrazie, jak i na iPadzie, gdzie wyświetlamy ikonę i tekst obok siebie. W szczególności na iPhone'ach ikona jest mniejsza, a pasek zakładek jest mniejszy, aby uzyskać nieco więcej miejsca w pionie.

1

oprócz Jana odpowiedź:

Jeśli masz więcej niż 4 bar tab przedmioty i nie chcą „więcej” przycisk trzeba podjąć inna klasa wielkości. A jeśli chcesz oryginalny scentralizowany układ elementów trzeba dodać inną metodę tak:

#import "PreIOS11TabBarController.h" 

@interface PreIOS11TabBarController() 

@end 

@implementation PreIOS11TabBarController 

// In iOS 11, UITabBarItem's have the title to the right of the icon in horizontally regular environments 
// (i.e. the iPad). In order to keep the title below the icon, it was necessary to subclass UITabBar and override 
// traitCollection to make it horizontally compact. 

- (UITraitCollection *)traitCollection { 
    return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified]; 
} 


- (void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 

    self.tabBar.itemPositioning = UITabBarItemPositioningCentered; 
} 

@end 
+0

To rozwiązanie blokuje ikony paska nawigacji :( –

13

Aby uniknąć bałaganu innych cech jest nie lepiej połączyć z superklas:

- (UITraitCollection *)traitCollection 
{ 
    UITraitCollection *curr = [super traitCollection]; 
    UITraitCollection *compact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; 

    return [UITraitCollection traitCollectionWithTraitsFromCollections:@[curr, compact]]; 
} 
+0

To jest rzeczywiście lepsze! – nolanw

+0

Awesome..to działa dla mnie. Gdy miałem już ustawioną klasę Compact na kolekcjonowanie cech, naprawiono elementy paska tabulacji, ale złamałem pasek nawigacyjny guziki.dziękuję –

+0

@BharatRaichur Subclass UITabBar nie UITabBarController następnie przesłonić '- (UITraitCollection *) traitCollection {...}' To nie będzie hamować twój pasek nawigacji –

17

na podstawie odpowiedzi John C, oto jest wersja Swift 3, które mogą być wykorzystane programowo bez konieczności Storyboard lub podklasy:

extension UITabBar { 
    // Workaround for iOS 11's new UITabBar behavior where on iPad, the UITabBar inside 
    // the Master view controller shows the UITabBarItem icon next to the text 
    override open var traitCollection: UITraitCollection { 
     if UIDevice.current.userInterfaceIdiom == .pad { 
      return UITraitCollection(horizontalSizeClass: .compact) 
     } 
     return super.traitCollection 
    } 
} 
+1

To nie jest zalecane, choć nie jestem zaskoczony usłyszeć, że to działa w tej chwili.Jeśli 'UITabBar' również nadpisuje' traitCollection', i/lub jeśli istnieje inny rozszerzenie (lub kategoria Objective-C) na 'UITabBar' gdzieś, który go implementuje, to wynik jest niezdefiniowany. Lepiej wyłączyć podklasę (jest to denerwujące) .Patrz https://stackoverflow.com/questions/5267034/category-conflicts, aby uzyskać więcej informacji: – nolanw

+0

@nolanw Czy istnieje sposób użycia podklasy, jeśli używasz tylko 'UITabBarController'?Uwaga: ta odpowiedź również działa w tym przypadku. –

+1

@DanRosenstark yep: użyj storyboardu. Mam scenorys w projekcie, który ma zwykły 'UITabBarController', którego jedynym dostosowaniem jest ustawienie klasy paska zakładek i ładuję go w kodzie. To ból w tyłku, ale jest bezpieczniejszy niż zawroty głowy i dużo bezpieczniejszy niż skakanie, nie ma konfliktów kategorii. – nolanw

0

Swift 4 wersji z podklasy że unika ext ension/kategoria nazywania kolizja:

class TabBar: UITabBar { 
    override var traitCollection: UITraitCollection { 
    guard UIDevice.current.userInterfaceIdiom == .pad else { 
     return super.traitCollection 
    } 

    return UITraitCollection(horizontalSizeClass: .compact) 
    } 
} 

Jeśli używasz interfejsu Builder, można wybrać kartę bar widok w UITabBarController sceny i zmienić jego klasy do TabBar w Identity Inspector:

enter image description here

Powiązane problemy