ios - top - safe area iphone x dimensions




iOS 11 guia de layout de área segura compatibilidade retroativa (9)

"guia de layout de área segura" é compatível com versões anteriores. Bem, a menos que você use no xib. Com storyboard parece ok.

Resolvi meu problema acessando a "Restrição de layout superior" do primeiro objeto na parte superior da minha visualização.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;

depois, alterei o valor Constant para essa restrição e atualizei a exibição. Por exemplo, se você usar uma barra de navegação (altura 44) mais a barra de status (altura 20):

if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
    _topLayoutConstraint.constant = 64;
    [self.view layoutIfNeeded];
}

Com SYSTEM_VERSION_LESS_THAN, que é definido assim:

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

Está habilitando os Guias de layout de área segura compatíveis com iOS abaixo de 11?


A compatibilidade com versões anteriores de áreas seguras para iOS 9 e iOS 10 só funciona se você estiver usando storyboards. Se você estiver usando xibs, não haverá um guia de layout para o qual retornar. https://forums.developer.apple.com/thread/87329

As soluções alternativas parecem ser

(a) migrar seus xibs para storyboards, ou

(b) adicione algumas restrições adicionais de forma programática.

Se (a) não é realmente uma opção, a abordagem manual será algo assim:

Supondo que você tenha uma visão no seu xib que você deseja manter dentro da área segura (ou seja, abaixo de qualquer barra de status ou barra de navegação).

  1. Adicione restrições em seu xib entre sua visualização e a área segura para iOS 11. Atribua a restrição superior a uma prioridade de 750.

  2. No seu controlador de visualização, adicione uma propriedade:

    @property (nonatomic, strong) NSLayoutConstraint *topLayoutConstraint;

    E então em viewDidLayoutSubviews:

    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
    
        if (@available(iOS 11, *)) {
            // safe area constraints already set
        }
        else {
            if (!self.topLayoutConstraint) {
                self.topLayoutConstraint = [self.<yourview>.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor];
                [self.topLayoutConstraint setActive:YES];
            }
        }
    }

    A nova restrição só será criada para o iOS 9 e iOS 10, tem uma prioridade padrão de 1000 e substitui a do xib.

  3. Repita para uma restrição inferior se precisar evitar o indicador inicial.

Versão Swift 4:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if #available(iOS 11, *) {
        // safe area constraints already set
    } else {
        if topLayoutConstraint == nil {
            topLayoutConstraint = <yourview>.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
            topLayoutConstraint?.isActive = true
        }
    }
}

Consegui trabalhar com os novos guias de layout da Área Segura e manter compatibilidade retroativa com o iOS 9 e o iOS 10: (EDIT: como apontado nos comentários de @NickEntin, esta implementação presumirá que há uma barra de status presente, o que não ser verdade na paisagem no iPhone X. Resultando em muito espaço para o topo (20 pontos) .Ele vai correr perfeitamente bem no entanto.

Por exemplo, se você deseja que uma vista fique 10 pontos abaixo da barra de status (e 10 pontos abaixo da caixa do sensor no iPhone X):

  1. No seu XIB, vá para File Inspector e ative o seguro marcando Use Safe Area Layout Guides .
  2. Criar uma restrição a partir do topo da vista para o topo da vista principal, com >= (maior que ou igual) restrição, constante 30 (30 porque queremos 10 pontos de espaçamento para a barra de status que é 20 pontos de altura) e prioridade High (750) .
  3. Crie uma restrição do topo da vista para o topo da Área Segura, com a restrição = (igual), constante 10 e prioridade Low (250).

O mesmo pode ser feito para uma vista na parte inferior (e para a esquerda / direita ou esquerda / direita para a Área Segura):

  1. No seu XIB, vá para File Inspector e ative o seguro marcando Use Safe Area Layout Guides .
  2. Crie uma restrição a partir da parte inferior da vista para a parte inferior da vista principal, com >= (maior que ou igual) restrição, constante 10 e prioridade High (750).
  3. Crie uma restrição desde a parte inferior da vista até a parte inferior da Área Segura, com a restrição = (igual), constante 10 e prioridade Low (250).

Definitivamente há pelo menos um problema de compatibilidade com as restrições de área segura do iOS 11 que observei no Xcode 9 GM - empurrou os controladores de visualização com restrições de área seguras.

Se a sua barra de navegação estiver oculta e você pressionar a visualização com restrição máxima da área segura, a visualização pressionada se sobrepõe à barra de status no iOS 9 e 10.

Se a barra de navegação estiver visível e "sob as barras superiores" desabilitada, a exibição pressionada ainda deslizará para baixo da barra de navegação para chegar ao topo da tela. A barra de navegação está posicionada corretamente.

No iOS 11, o layout estará correto em ambos os casos.

Aqui está um exemplo simples: http://www.filedropper.com/foobar

E aqui está um vídeo dele com barra de navegação oculta (iOS 10.3 à esquerda, iOS 11 à direita): https://vimeo.com/234174841/1e27a96a87

Aqui está uma versão em que a barra de navegação está visível (ativada na ponta): https://vimeo.com/234316256/f022132d57

Eu arquivei isso como Radar # 34477706.

Obrigado ao @Sander por apontar o caso visível da barra de navegação.


Eu encontrei uma maneira mais conveniente, onde você só precisa subclasse o NSLayoutConstraint que é fixado ao seu safeArea .

É meio hacky, já que você tem que pegar o ViewController de um UIView, mas na minha opinião, é uma alternativa fácil e boa até que a Apple finalmente conserte a compatibilidade com o safeArea no Xibs.

Subclasse:

class SafeAreaBackwardsCompatabilityConstraint: NSLayoutConstraint {
private weak var newConstraint: NSLayoutConstraint?

override var secondItem: AnyObject? {
    get {
        if #available(iOS 11.0, *) {}
        else {
            if let vc = (super.secondItem as? UIView)?.parentViewController, newConstraint == nil {
                newConstraint = (self.firstItem as? UIView)?.topAnchor.constraint(equalTo: vc.topLayoutGuide.bottomAnchor)
                newConstraint?.isActive = true
                newConstraint?.constant = self.constant
            }
        }
        return super.secondItem
    }
}

override var priority: UILayoutPriority {
    get {
        if #available(iOS 11.0, *) { return super.priority }
        else { return 750 }
    }
    set { super.priority = newValue }
}
}

private extension UIView {
var parentViewController: UIViewController? {
    var parentResponder: UIResponder? = self
    while parentResponder != nil {
        parentResponder = parentResponder!.next
        if let viewController = parentResponder as? UIViewController {
            return viewController
        }
    }
    return nil
}
}

Xib:


Eu estava usando isso no Objective-C com um bom resultado para o iOS 10. Caso você use o SafeArea no seu xib, então você pode adicionar em seu viewDidLoad :

if (@available(iOS 11.0, *)) {}
else {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

Se você usa xibs sem storyboard, então eles não têm guias de layout no ios 10. Então, mova o xib para o storyboard para ter compatibilidade com versões anteriores.


Sim, seu projeto / aplicativo funcionará nas versões do iOS anteriores ao iOS 11 sem qualquer problema. Nas versões do iOS anteriores a 11, ele substitui / considera o Layout de área segura em AutoLayout normal e segue o guia de layout Regras de superior e inferior.

Eu testei meu projeto existente com e sem 'SafeAreaLayout' em ambas as plataformas (iOS 11 e iOS 10 inverso). Está funcionando bem.

Apenas certifique-se:

  • Se você projetou seu projeto / Interface do usuário no AutoLayout; restrições do seu UIElement segue / relativo ao guia de layout Top e Bottom (não para o superview). Assim, com um único clique (habilitar) na opção SafeAreaLayout, o layout do SafeArea será implementado automaticamente para todos os arquivos do Interface Builders em seu storyboard.

  • Se você projetou seu projeto / interface do usuário em SafeAreaLayout; em seguida, ele seguirá automaticamente o guia de layout Superior e Inferior no iOS para trás.

Aqui está a amostra instantânea com o resultado. Ao ativar ou desativar o layout da Área Segura, não afetará o design existente.

Layout de Área Segura:

AutoLayout

Em suma, uma resposta à sua pergunta é: "Ativando guias de layout de área segura compatíveis com o iOS antes de 11"

Você pode implementar o Layout da Área Segura no seu projeto / aplicativo e ele funcionará bem com as versões anteriores do iOS, convertendo o Layout de Área Segura no Layout Superior e Inferior.


Aqui está o meu wrapper de solução iOS 9 para iOS 11+ em 4+ rápido

    let safeAreaTopAnchor:NSLayoutYAxisAnchor?
    if #available(iOS 11.0, *) {
        safeAreaTopAnchor = contentView.safeAreaLayoutGuide.topAnchor
    } else {
        // Fallback on earlier versions

        var parentViewController: UIViewController? {
            var parentVCResponder: UIResponder? = self
            while parentVCResponder != nil {
                parentVCResponder = parentVCResponder!.next
                if let viewController = parentVCResponder as? UIViewController {
                    return viewController
                }
            }
            return nil
        }

        safeAreaTopAnchor = parentViewController?.topLayoutGuide.bottomAnchor

    }




safearealayoutguide