Toute personne ayant un problème avec le simulateur iPhone X autour du composant UITabBar?
Les miens semblent rendre les icônes et le titre superposés, je ne suis pas sûr de ne rien manquer, je l’ai également exécuté dans le simulateur de l’iPhone 8, et un des appareils réels où l’apparence est satisfaisante, comme indiqué sur le story board.
iPhone X:
iPhone 8
J'ai pu contourner le problème en appelant simplement invalidateIntrinsicContentSize sur la barre UITabBar dans viewDidLayoutSubviews.
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.tabBar invalidateIntrinsicContentSize];
}
Remarque: le bas de la barre d'onglets devra être contenu au bas de la vue principale, plutôt que dans la zone sécurisée, et la barre d'onglets ne devrait pas avoir de contrainte de hauteur.
La réponse fournie par VoidLess ne résout que partiellement les problèmes de TabBar. Cela résout les problèmes de mise en page dans la barre d’onglet, mais si vous utilisez viewcontroller qui masque la barre d’onglet, celle-ci est restituée de manière incorrecte lors des animations (pour le reproduire, il est préférable d’utiliser 2 séquences de 2, 1 voir la barre de tabulation étant rendue hors de propos). Le code ci-dessous corrige les deux problèmes. Bon travail Apple.
class SafeAreaFixTabBar: UITabBar {
var oldSafeAreaInsets = UIEdgeInsets.zero
@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
if oldSafeAreaInsets != safeAreaInsets {
oldSafeAreaInsets = safeAreaInsets
invalidateIntrinsicContentSize()
superview?.setNeedsLayout()
superview?.layoutSubviews()
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if #available(iOS 11.0, *) {
let bottomInset = safeAreaInsets.bottom
if bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {
size.height += bottomInset
}
}
return size
}
override var frame: CGRect {
get {
return super.frame
}
set {
var tmp = newValue
if let superview = superview, tmp.maxY !=
superview.frame.height {
tmp.Origin.y = superview.frame.height - tmp.height
}
super.frame = tmp
}
}
}
Code Objective-C:
@implementation VSTabBarFix {
UIEdgeInsets oldSafeAreaInsets;
}
- (void)awakeFromNib {
[super awakeFromNib];
oldSafeAreaInsets = UIEdgeInsetsZero;
}
- (void)safeAreaInsetsDidChange {
[super safeAreaInsetsDidChange];
if (!UIEdgeInsetsEqualToEdgeInsets(oldSafeAreaInsets, self.safeAreaInsets)) {
[self invalidateIntrinsicContentSize];
if (self.superview) {
[self.superview setNeedsLayout];
[self.superview layoutSubviews];
}
}
}
- (CGSize)sizeThatFits:(CGSize)size {
size = [super sizeThatFits:size];
if (@available(iOS 11.0, *)) {
float bottomInset = self.safeAreaInsets.bottom;
if (bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90)) {
size.height += bottomInset;
}
}
return size;
}
- (void)setFrame:(CGRect)frame {
if (self.superview) {
if (frame.Origin.y + frame.size.height != self.superview.frame.size.height) {
frame.Origin.y = self.superview.frame.size.height - frame.size.height;
}
}
[super setFrame:frame];
}
@end
Il y a une astuce par laquelle nous pouvons résoudre le problème.
Il suffit de placer votre UITabBar dans un UIView.
Cela fonctionne vraiment pour moi.
Ou vous pouvez suivre ceci Lien pour plus de détails.
remplace UITabBar
sizeThatFits(_)
pour safeArea
extension UITabBar {
static let height: CGFloat = 49.0
override open func sizeThatFits(_ size: CGSize) -> CGSize {
guard let window = UIApplication.shared.keyWindow else {
return super.sizeThatFits(size)
}
var sizeThatFits = super.sizeThatFits(size)
if #available(iOS 11.0, *) {
sizeThatFits.height = UITabBar.height + window.safeAreaInsets.bottom
} else {
sizeThatFits.height = UITabBar.height
}
return sizeThatFits
}
}
Déplacer la barre d'onglets 1 point du bas a fonctionné pour moi.
Bien sûr, vous obtiendrez un vide que vous devrez combler d'une certaine manière, mais le texte/les icônes sont maintenant correctement positionnés.
J'ai eu le même problème.
Si je règle une constante non nulle sur la contrainte inférieure de la barre UITabBar sur la zone de sécurité:
Cela commence à fonctionner comme prévu ...
C’est le seul changement que j’ai fait et je ne sais pas pourquoi cela fonctionne, mais si quelqu'un le faisait, j'aimerais bien savoir.
J'ai ajouté ceci à viewWillAppear
de ma coutume UITabBarController
, car aucune des réponses fournies ne fonctionnait pour moi:
tabBar.invalidateIntrinsicContentSize()
tabBar.superview?.setNeedsLayout()
tabBar.superview?.layoutSubviews()
J'ai finalement compris cela après des heures à maudire Apple.
UIKit gère effectivement cela pour vous, et il semble que les éléments de la barre de tabulation décalés sont dus à une configuration incorrecte (et probablement à un bogue UIKit réel). Il n'est pas nécessaire de sous-classer ou une vue en arrière-plan.
Cela fonctionne même dans le constructeur d'interface.
Ce qui est vraiment stupide, c’est que vous pouvez réellement voir le bogue dans IB aussi, même si vous ajoutez les contraintes exactes que IB ajoute dans les étapes ci-dessus!
Corrigé en utilisant UITabBar sous-classé pour appliquer les safeAreaInsets:
class SafeAreaFixTabBar: UITabBar {
var oldSafeAreaInsets = UIEdgeInsets.zero
@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
if oldSafeAreaInsets != safeAreaInsets {
oldSafeAreaInsets = safeAreaInsets
invalidateIntrinsicContentSize()
superview?.setNeedsLayout()
superview?.layoutSubviews()
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if #available(iOS 11.0, *) {
let bottomInset = safeAreaInsets.bottom
if bottomInset > 0 && size.height < 50 {
size.height += bottomInset
}
}
return size
}
}
Résolu pour moi en appelant [tabController.view setNeedsLayout];
après avoir rejeté le modal du bloc d'achèvement.
[vc dismissViewControllerAnimated:YES completion:^(){
UITabBarController* tabController = [UIApplication sharedApplication].delegate.window.rootViewController;
[tabController.view setNeedsLayout];
}];
Mon cas était que j'avais défini une hauteur UITabBar personnalisée dans mon UITabBarController, comme ceci:
override func viewWillLayoutSubviews() {
var tabFrame = tabBar.frame
tabFrame.size.height = 60
tabFrame.Origin.y = self.view.frame.size.height - 60
tabBar.frame = tabFrame
}
La suppression de ce code était la solution permettant à TabBar de s'afficher correctement sur iPhone X.
La hauteur de la barre UITabBar augmente au-dessus du bouton/de la ligne de base, mais dessine la sous-vue à son emplacement d'origine et superpose la base UITabBarItem sur la sous-vue.
Pour contourner le problème, vous pouvez détecter l'iPhone X, puis réduire la hauteur de la vue de 32 pixels pour vous assurer que la barre d'onglets est affichée dans la zone sécurisée au-dessus de la ligne de base.
Par exemple, si vous créez votre TabBar par programme, remplacez
self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = self.tabBarController;
Avec ça:
#define IS_IPHONEX (([[UIScreen mainScreen] bounds].size.height-812)?NO:YES)
self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = [[UIViewController alloc] init] ;
if(IS_IPHONEX)
self.window.rootViewController.view.frame = CGRectMake(self.window.rootViewController.view.frame.Origin.x, self.window.rootViewController.view.frame.Origin.y, self.window.rootViewController.view.frame.size.width, self.window.rootViewController.view.frame.size.height + 32) ;
[self.window.rootViewController.view addSubview:self.tabBarController.view];
self.tabBarController.tabBar.barTintColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;
self.window.rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;
NOTE: Cela pourrait bien être un bug, car la taille de la vue et la disposition de la barre d'onglets sont définies par le système d'exploitation. Il devrait probablement s'afficher conformément à la capture d'écran d'Apple dans les instructions pour l'interface humaine de l'iPhone X ici: https://developer.Apple.com/ios/human-interface-guidelines/overview/iphone-x/
J'ai rencontré ce problème aujourd'hui avec un UITabBar ajouté manuellement au contrôleur de vue dans le storyboard. Lors de l'alignement au bas de la zone sécurisée avec une constante de 0, le problème était résolu, mais sa valeur par 1 résolvait le problème. Avoir le UITabBar jusqu'à 1 pixel de plus que la normale était acceptable pour mon application.
J'avais le même problème lorsque j'essayais de définir le cadre de UITabBar dans mon TabBarController personnalisé.
self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);
Quand je viens de l'ajuster à la nouvelle taille, le problème disparut
if(IS_IPHONE_X){
self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kPhoneXTabBarHeight, self.view.frame.size.width, kPhoneXTabBarHeight);
}
else{
self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);
}
Je me suis gratté la tête à cause de ce problème. Il semble être associé à la façon dont le tabBar est initialisé et ajouté à la hiérarchie des vues. J'ai également essayé les solutions ci-dessus, comme appeler invalidateIntrinsicContentSize
, définir le cadre, et aussi bottomInsets
dans une sous-classe UITabBar. Ils semblent fonctionner cependant temporairement et ils rompent avec un autre scénario ou régressent la barre d’onglet en provoquant un problème de mise en page ambigu. Lorsque je déboguais le problème, j’essayais d’attribuer les contraintes de hauteur à UITabBar et centerYAnchor, mais le problème n’a pas été résolu. J'ai réalisé dans view debugger que la hauteur de tabBar était correcte avant et après la reproduction du problème, ce qui m'a amené à penser que le problème se trouvait dans les sous-vues. J'ai utilisé le code ci-dessous pour résoudre ce problème avec succès sans faire régresser aucun autre scénario.
- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
if (DEVICE_IS_IPHONEX())
{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
for (UIView *view in self.tabBar.subviews)
{
if ([NSStringFromClass(view.class) containsString:@"UITabBarButton"])
{
if (@available (iOS 11, *))
{
[view.bottomAnchor constraintEqualToAnchor:view.superview.safeAreaLayoutGuide.bottomAnchor].active = YES;
}
}
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
[self.tabBar layoutSubviews];
}];
}
}
Hypothèses: je le fais uniquement pour iPhone X, car il ne semble pas pouvoir se reproduire sur un autre appareil pour le moment. Est basé sur l'hypothèse qu'Apple ne change pas le nom de la classe UITabBarButton dans les futures versions iOS. Nous ne le faisons sur UITabBarButton que lorsque cela signifie que si Apple ajoute davantage de sous-vues internes à UITabBar, il se peut que nous devions modifier le code pour l'ajuster.
Sachez que cela fonctionne, sera ouvert aux suggestions et améliorations!
Il devrait être simple de créer un équivalent Swift pour cela.
A partir de ce tutoriel:
https://github.com/eggswift/ESTabBarController
et après l’initialisation de la barre d’onglet en écrivant cette ligne dans la classe appdelegate
(self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator
Résout mon problème de barre de tabulation.
J'espère que ça résoud ton problème
Merci
Pour moi, cela a résolu tous les problèmes:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let currentHeight = tabBar.frame.height
tabBar.frame = CGRect(x: 0, y: view.frame.size.height - currentHeight, width: view.frame.size.width, height: currentHeight)
}
Pour moi, supprimez [self.tabBar setBackgroundImage:]
work, c'est peut-être un bug UIKit
La solution la plus simple que j'ai trouvée consistait simplement à ajouter un espace de 0,2 point entre le bas de la barre de tabulation et le bas de la zone safeAreaLayoutGuide.bottomAnchor.
tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -0.2)
Pour l'iPhone, vous pouvez le faire, sous-classe UITabBarController.
class MyTabBarController: UITabBarController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.tabBar.invalidateIntrinsicContentSize()
}
}
}
Allez dans Storyboard et autorisez Utilisez le Guide de présentation des zones sûres et modifiez la classe de UITabbarController en MyTabBarController
P.S Cette solution n'est pas testée dans le cas d'applications universelles et iPad.
Si vous avez une contrainte de hauteur pour la barre d'onglets, essayez de la supprimer.
Face au même problème et en supprimant cela résolu le problème.
J'utilisais un UITabBarController
dans le storyboard et au début, tout fonctionnait correctement pour moi, mais après la mise à niveau vers la version Xcode plus récente, les problèmes liés à la hauteur de la barre de tabulation ont commencé à apparaître.
Pour moi, le correctif consistait à supprimer le UITabBarController
existant du storyboard et à le recréer en le faisant glisser à partir de la bibliothèque d'objets de générateur d'interface.
J'ai créé un nouveau UITabBarController dans mon scénario et poussé tous les contrôleurs de vue vers ce nouveau UITabBarConttoller. Donc, tout fonctionne bien dans le simulateur iPhone X.
essayez de changer l'écran de démarrage avec la taille @ 3x est (3726 × 6624)