2017-06-29 89 views
28

我已經構建了我的應用程序使用新的Xcode 9 beta for ios 11.我發現UITabBar的問題,其中的項目是通過UITabBar傳播和標題是正確的圖像對齊。我試圖改變代碼來使它工作,但仍然不成功。ios 11 UITabBar UITabBarItem定位問題

IOS 10+

enter image description here

IOS 11

enter image description here

我可以用tabBarItem.titlePositionAdjustment 更改標題的位置,但是,這不是我的要求,因爲它應該自動進入貝婁圖像本身。我試圖設置tabbar.itemPositioning to UITabBarItemPositioningCentered,也試圖改變itemSpacingwidth,但仍然沒有工作。有人能幫我理解爲什麼會發生這種情況,以及如何解決這個問題我希望它喜歡ios 10+版本,圖像是從iPad的最左邊角落拍攝的。

+7

這是一個功能,而不是一個錯誤。 – matt

+0

這不僅僅是Objective-C的問題,而且通常與Objective-C和Swift應用程序都有關係。 – Jeet

+0

功能? IDK的。更多的情況是蘋果「改善」了一些東西,卻沒有考慮到所有的後果。 –

回答

27

我正在維護一個大型的iPad應用程序,主要編寫Objective-C,它已經存活了幾個iOS版本。我遇到了這種情況,我需要iOS 11以前的標籤欄外觀(圖標位於標題的上方,而不是旁邊),用於標籤欄。我的解決方案是創建一個UITabBar的子類,它覆蓋traitCollection方法,以便它總是返回一個橫向緊湊的特徵集合。這會導致iOS 11在所有標籤欄按鈕的圖標下方顯示標題。

爲了使用它,將故事板中的標籤欄的自定義類設置爲這個新的子類,並將代碼中指向標籤欄的任何插座改爲這種新類型(不要忘記導入下面的頭文件)。

.h文件是在這種情況下幾乎空:

// 
// MyTabBar.h 
// 

#import <UIKit/UIKit.h> 

@interface MyTabBar : UITabBar 

@end 

這裏是。與traitCollection方法的實現M檔:

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

我不使用故事板/ IB,但我能夠通過繼承UITabBarController而不是UITabBar並覆蓋相同的traitCollection方法來獲得完全相同的效果。 – massimobio

+0

不僅! 它也適用於使用UITabBarController的子類使用此修補程序的故事板/ IB ... –

+2

實際上劃傷它。不推薦子類化UITabBarController,事實上導航條在iOS 11 GM中打破了這一點。 – massimobio

10

注意: This fix above似乎很好地工作。不知道它將來如何工作,但現在它工作得很好。


根據this WWDC talk,這是新的行爲:

  • iPhone在景觀
  • iPad上所有的時間

如果我讀正確,此行爲不可更改:

我們爲標籤欄提供了全新的外觀,無論是在橫向還是在iPad上,我們都會並排顯示圖標和文本。特別是在iPhone上,圖標更小,標籤欄更小,可以垂直放置更多空間。

1

除了約翰的回答是:

如果你有超過4個標籤欄項目,不希望「更多」按鈕,你必須要一個不同的尺寸等級。如果你想項目的原始中心佈局必須添加另一種方法,像這樣:

#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

這個解決方案剎車導航欄圖標:( –

13

爲了避免搞亂任何其他性狀難道不是更好地與超結合:

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

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

這確實更好! – nolanw

+0

真棒..這對我有用當我剛剛設置爲特徵集合的緊湊大小類,它修復了我的標籤欄項目,但打破了我的導航欄按鈕。謝謝!! –

+0

@BharatRaichur子類UITabBar不是UITabBarController,然後重寫' - (UITraitCollection *)traitCollection {...}'。這不會制動你的導航欄。 –

17

根據約翰·C·的答案,這裏是一個可以編程使用,而不需要故事板或子類的斯威夫特3版本:

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

這不推薦,雖然我並不感到驚訝如果'UITabBar'也覆蓋'traitCollection',並且/或者在UITabBar上有另一個擴展(或者Objective-C類別)在某個地方實現它,那麼結果是不確定的。更好的亞類(煩人的是這樣)。有關更多信息,請參閱https://stackoverflow.com/questions/5267034/category-conflicts。 – nolanw

+0

@nolanw有沒有辦法使用子類if你只是使用'UITabBarController'?注意:這個答案也適用於這種情況。 –

+1

@DanRosenstark是的:使用故事板。我在一個有簡單的'UITabBarController'的項目中有一個storyboard,它的唯一自定義就是設置它的標籤欄的類,並將它加載到代碼中。這是一個痛苦的屁股,但它比安然無恙,比跳更安全,沒有類別衝突。 – nolanw

0

斯威夫特4版採用了子類,避免轉ension /類別命名衝突:

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

    return UITraitCollection(horizontalSizeClass: .compact) 
    } 
} 

如果您使用Interface Builder,您可以在UITabBarController場景選擇標籤欄視圖,並改變其類TabBar的身份檢查:

enter image description here