it-swarm.com.de

iOS 11 iPhone X-Simulator - TabBar-Symbole und Titel, die übereinander gerendert werden

Wer hat Probleme mit dem iPhone X-Simulator rund um die UITabBar-Komponente?

Meine scheinen die Symbole und den Titel übereinander zu rendern, ich bin mir nicht sicher, ob mir etwas fehlt, ich habe es auch im iPhone 8-Simulator ausgeführt und ein Gerät, bei dem es genau so aussieht, wie es auf der Storyboard.

iPhone X:

 iPhone X UITabBar bug

iPhone 8

 iPhone 8 UITabBar works

114
adrian chen

Ich konnte das Problem umgehen, indem ich invalidateIntrinsicContentSize auf der UITabBar in viewDidLayoutSubviews aufrief.

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self.tabBar invalidateIntrinsicContentSize];
}

Hinweis: Der untere Teil der Registerkartenleiste muss sich am unteren Rand der Hauptansicht und nicht im sicheren Bereich befinden. Die Registerkartenleiste sollte keine Höhenbeschränkung haben.

34
David Hooper

Die von VoidLess bereitgestellte Antwort behebt TabBar-Probleme nur teilweise. Es behebt Layoutprobleme in der Tab-Leiste, aber wenn Sie ViewController verwenden, der die Tab-Leiste verbirgt, wird die Tab-Leiste während der Animationen falsch dargestellt (um sie zu reproduzieren, haben Sie am besten 2 Segmente - einen modalen und einen Push. Wenn Sie die Segmente wechseln, können Sie dies tun sehen, dass die Tab-Leiste nicht richtig dargestellt wird). Der folgende Code behebt beide Probleme. Gute Arbeit, 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
        }
    }
}

Ziel-C-Code:

@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
22

Es gibt einen Trick, mit dem wir das Problem lösen können.

Fügen Sie einfach Ihre UITabBar in eine UIView ein.

Das funktioniert wirklich für mich.

Oder Sie können diesem Link für weitere Details folgen.

19
Avineet Gupta

Überschreiben Sie UITabBarsizeThatFits(_) für 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
    }
}
8
Cruz

Das Verschieben der Tab-Leiste 1 Punkt von unten hat für mich funktioniert.

Natürlich entsteht dadurch eine Lücke, die Sie ausfüllen müssen, aber der Text/die Symbole sind jetzt richtig positioniert.

7
deej

Ich hatte das gleiche Problem.

 enter image description here

Wenn ich für die untere Einschränkung der UITabBar eine Konstante ungleich Null für den sicheren Bereich einrichte:

 enter image description here

Es fängt an, wie erwartet zu arbeiten ... 

 enter image description here

Das ist die einzige Änderung, die ich vorgenommen habe, und ich habe keine Ahnung, warum es funktioniert, aber wenn jemand es tut, würde ich es gerne wissen. 

7
moliveira

Ich habe dies zu viewWillAppear meiner benutzerdefinierten UITabBarController hinzugefügt, da keine der angegebenen Antworten für mich funktioniert:

tabBar.invalidateIntrinsicContentSize()
tabBar.superview?.setNeedsLayout()
tabBar.superview?.layoutSubviews()
6
aaannjjaa

Aha! Es ist wirklich magisch!

Ich fand das schließlich heraus, nachdem ich Apple stundenlang beschimpft hatte. 

UIKit erledigt dies tatsächlich für Sie, und es scheint, dass die Elemente der verschobenen Tab-Leiste auf falsche Einstellungen (und möglicherweise einen tatsächlichen UIKit-Fehler) zurückzuführen sind. Es ist keine Unterklasse oder eine Hintergrundansicht erforderlich.

UITabBar funktioniert "nur", wenn es auf den unteren Rand des Superview beschränkt ist, NICHT auf den sicheren unteren Bereich.

Es funktioniert sogar im Interface Builder. 

Richtiges Setup

 Working in IB

  1. Ziehen Sie eine UITabBar im Interface-Builder als iPhone X an die Stelle, an der sie im unteren Bereich des sicheren Bereichs einrastet. Wenn Sie es ablegen, sollte es korrekt aussehen (füllen Sie den Raum bis zum unteren Rand aus). 
  2. Sie können dann ein "Fehlende Einschränkungen hinzufügen" ausführen, und IB fügt die richtigen Einschränkungen hinzu, und Ihre Tab-Leiste funktioniert auf allen iPhones magisch! (Beachten Sie, dass die untere Einschränkung so aussieht, als hätte sie einen konstanten Wert, der der Höhe des unsicheren Bereichs des iPhone X entspricht, die Konstante ist jedoch tatsächlich 0).

Manchmal klappt es immer noch nicht

 Broken in IB

Was wirklich dumm ist, ist, dass Sie den Fehler auch in IB sehen können, selbst wenn Sie die genauen Einschränkungen hinzufügen, die IB in den obigen Schritten hinzufügt.

  1. Ziehen Sie eine UITabBar heraus und schnappen Sie sie nicht im unteren Bereich des sicheren Bereichs ein
  2. Fügen Sie alle führenden, nachlaufenden und unteren Einschränkungen zum Superview (nicht dem sicheren Bereich) hinzu Dies wird seltsam behoben, wenn Sie im Einschränkungsinspektor für die untere Einschränkung ein "Erstes und Zweites Element umkehren" ausführen. ¯_ (ツ) _/¯
5
RyanM

Behoben mit subclassed UITabBar, um safeAreaInsets anzuwenden:

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
    }
}
5
VoidLess

Für mich gelöst, indem Sie [tabController.view setNeedsLayout]; aufrufen, nachdem Sie den Modal in Completion-Block abgewiesen haben.

[vc dismissViewControllerAnimated:YES completion:^(){ 
     UITabBarController* tabController = [UIApplication sharedApplication].delegate.window.rootViewController;
     [tabController.view setNeedsLayout];
}];
3
yogevbd

Mein Fall war, dass ich eine benutzerdefinierte UITabBar-Höhe in meinem UITabBarController eingestellt hatte, wie folgt:

  override func viewWillLayoutSubviews() {            
        var tabFrame = tabBar.frame
        tabFrame.size.height = 60
        tabFrame.Origin.y = self.view.frame.size.height - 60
        tabBar.frame = tabFrame
    }

Durch das Entfernen dieses Codes konnte die TabBar auf dem iPhone X korrekt angezeigt werden.

2
Gytis

Die Höhe der UITab-Leiste wird so erhöht, dass sie über der Home-Schaltfläche Linie liegt, zeichnet jedoch die Unteransicht an ihrer ursprünglichen Position und überlagert das UITabBarItem über der Unteransicht.

Als Problemumgehung können Sie das iPhone X erkennen und dann die Höhe der Ansicht um 32 Pixel verkleinern, um sicherzustellen, dass die Registerkartenleiste im sicheren Bereich über der Startlinie angezeigt wird.

Zum Beispiel, wenn Sie Ihre TabBar programmgesteuert ersetzen

self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = self.tabBarController;

Mit diesem:

#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] ;

HINWEIS: Dies kann durchaus ein Fehler sein, da die Ansichtsgrößen und das Layout der Registerkartenleiste vom Betriebssystem festgelegt werden. Es sollte wahrscheinlich laut Apple-Screenshot in den iPhone X Human Interface-Richtlinien hier angezeigt werden:/- https://developer.Apple.com/ios/human-interface-guidelines/overview/iphone-x/

2
A.Badger

Wählen Sie die Tab-Leiste aus und setzen Sie das Kontrollkästchen "Bereich relativ zum Rand speichern" im Inspektor-Editor wie folgt: 

 enter image description here

1
AnnGoro

Dies ist mir heute mit einer UITabBar begegnet, die manuell zum Ansichts-Controller im Storyboard hinzugefügt wurde. Wenn Sie sich mit einer Konstante von 0 am unteren Rand des sicheren Bereichs ausrichten, würde ich das Problem erhalten, aber die Änderung auf 1 würde das Problem beheben. Die UITabBar um 1 Pixel höher als normal zu haben, war für meine Anwendung akzeptabel.

1
Alan MacGregor

Ich hatte das gleiche Problem, als ich versuchte, den Rahmen von UITabBar in meinem benutzerdefinierten TabBarController festzulegen.

self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);

Als ich es einfach an die neue Größe anpasste, ging das Problem weg

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);
}
1
Evgeny

Ich habe mir über dieses Problem den Kopf gekratzt. Es scheint zu sein, wie die Tab-Leiste initialisiert und zur Ansichtshierarchie hinzugefügt wird. Ich habe auch die obigen Lösungen ausprobiert, wie den Aufruf von invalidateIntrinsicContentSize, das Setzen des Frames und auch bottomInsets innerhalb einer UITabBar-Unterklasse. Sie scheinen jedoch vorübergehend zu funktionieren, und sie lösen ein anderes Szenario auf oder führen zu einer Regression der Registerkartenleiste, was zu mehrdeutigen Layoutproblemen führt. Beim Debuggen des Problems habe ich versucht, der UITabBar und dem centerYAnchor die Höhenbeschränkungen zuzuweisen. Das Problem wurde jedoch nicht behoben. In View Debugger wurde mir klar, dass die Höhe der TabBar vor und nach der Wiedergabe des Problems korrekt war. Dies führte mich zu der Annahme, dass das Problem in den Unteransichten lag. Ich habe den folgenden Code verwendet, um dieses Problem erfolgreich zu beheben, ohne ein anderes Szenario zu regressieren. 

- (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];
        }];
    }
}

Annahmen: Ich mache dies nur für das iPhone X, da es momentan auf keinem anderen Gerät reproduziert zu werden scheint. Stützt sich auf die Annahme, dass Apple den Namen der UITabBarButton-Klasse in zukünftigen iOS-Versionen nicht ändert. Wir machen dies auf UITabBarButton nur dann, wenn bedeutet, wenn Apple weitere interne Unteransichten in UITabBar hinzufügt, müssen wir möglicherweise den Code ändern, um dies anzupassen. 

Bitte, lass mich wissen, ob dies funktioniert, ist offen für Vorschläge und Verbesserungen! 

Es sollte einfach sein, ein Swift-Äquivalent zu erstellen. 

1
Rushabh

Aus diesem Tutorial:

https://github.com/eggswift/ESTabBarController

und nach der Initialisierung der Tab-Leiste diese Zeile in appdelegate-Klasse schreiben

(self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator

Löst mein Problem mit der Tab-Leiste.

Hoffe, es löst dein Problem

Vielen Dank

1
Siddh

Für mich wurden alle Probleme behoben:

    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)
    }
0
Durdu

Entfernen Sie [self.tabBar setBackgroundImage:] work für mich, vielleicht ist es ein UIKit-Fehler

0
KelaKing

Die einfachste Lösung, die ich gefunden habe, war, einfach einen Abstand von 0,2 pt zwischen dem unteren Rand der Tab-Leiste und dem unteren Teil des safeAreaLayoutGuide.bottomAnchor hinzuzufügen.

tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -0.2)
0
Delta Whiskey

Für das iPhone können Sie dies tun, Subclass UITabBarController.

class MyTabBarController: UITabBarController {

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if #available(iOS 11, *) {
        self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true
        self.tabBar.invalidateIntrinsicContentSize()
    }
  }
}

Gehe zum Storyboard und erlaube Use Safe Area Layout Guide und ändere die Klasse von UITabbarController in MyTabBarController

P.S Diese Lösung wird bei universeller Anwendung und iPad nicht getestet. 

0
NaXir

Wenn Sie eine Höhenbeschränkung für die Tab-Leiste haben, versuchen Sie sie zu entfernen.

Konfrontierte das gleiche Problem und löste das Problem. 

0
rustylepord

Ich hatte ein ähnliches Problem, zuerst wurde es richtig gerendert, aber nachdem ich badgeValue auf einem der tabBarItem eingerichtet hatte, brach es das Layout. Was für mich funktionierte, ohne UITabBar zu verwenden, war dies in meiner bereits erstellten UITabBarController-Unterklasse.

-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    NSLayoutYAxisAnchor *tabBarBottomAnchor = self.tabBar.bottomAnchor;
    NSLayoutYAxisAnchor *tabBarSuperviewBottomAnchor = self.tabBar.superview.bottomAnchor;
    [tabBarBottomAnchor constraintEqualToAnchor:tabBarSuperviewBottomAnchor].active = YES;
    [self.view layoutIfNeeded];
}

Ich habe tabBar Superview verwendet, um sicherzustellen, dass sich die Abhängigkeiten/Anker in derselben Ansichtshierarchie befinden und Abstürze vermeiden.

Da dies nach meinem Verständnis ein UIKit-Fehler zu sein scheint, müssen wir lediglich die Einschränkungen für die Tab-Leiste neu schreiben bzw. neu festlegen, damit die Auto-Layout-Engine die Tab-Leiste wieder korrekt anordnen kann.

0
rgkobashi

Ich habe ein UITabBarController im Storyboard verwendet und es funktionierte zunächst in Ordnung für mich, aber nach dem Upgrade auf eine neuere Xcode-Version gab es Probleme mit der Höhe der TabBar.

Für mich bestand der Fix darin, das vorhandene UITabBarController aus dem Storyboard zu löschen und durch Ziehen aus der Interface Builder Objects Library neu zu erstellen.

0
enigma

Ich habe einen neuen UITabBarController in meinem Storyboard erstellt und alle View-Controller auf diesen neuen UITabBarConttoller übertragen. Alle funktionieren also gut mit dem iPhone X-Simulator.

0

versuchen Sie, den Startbildschirm mit @ 3x zu ändern (3726 × 6624).

0
Sob7y