Pergunta

Eu tenho uma visão personalizada que não está recebendo mensagens layoutSubview durante a animação.

Eu tenho uma visão que enche a tela. Tem um subexibição personalizado na parte inferior da tela que redimensiona corretamente na Interface Builder se eu mudar a altura da barra de navegação. layoutSubviews é chamada quando a vista é criado, mas nunca novamente. Meus subviews estão correctamente definidos. Se eu alternar a barra de status na chamada fora, layoutSubviews do subexibição não é chamado em tudo, embora a vista principal não animar o seu redimensionamento.

Em que circunstâncias é layoutSubviews realmente chamado?

Eu tenho set autoresizesSubviews para NO para minha exibição personalizada. E no Interface Builder tenho o topo e suportes de fundo eo conjunto seta vertical.


Outra parte do quebra-cabeça é que a janela deve ser feita chave:

[window makeKeyAndVisible];

de outra pessoa os subviews não são redimensionadas automaticamente.

Foi útil?

Solução 5

Eu segui o baixo solução para a insistência de Interface Builder que molas não pode ser alterado em uma visão que tem os elementos da tela simuladas ligado (barra de status, etc.). Desde as molas estavam fora para a vista principal, essa visão não poderia alterar o tamanho e, portanto, foi rolada para baixo em sua totalidade quando o bar na chamada apareceu.

Virando as características simuladas off, em seguida, redimensionar a vista e definir as fontes corretamente causado a animação para ocorrer e meu método a ser chamado.

Um problema adicional na depuração isso é que o simulador sai do aplicativo quando o estado-call é alternado através do menu. Saia do app = nenhum depurador.

Outras dicas

Eu tinha uma pergunta semelhante, mas não ficou satisfeito com a resposta (ou qualquer que eu poderia encontrar na net), então eu tentei-lo em prática e aqui é o que eu tenho:

  • init não causa layoutSubviews para ser chamado (duh)
  • causas addSubview: layoutSubviews a ser chamado na visualizar sendo adicionado, a visão está sendo adicionado a (ver alvo), e todo o subviews do alvo
  • vista setFrame inteligentemente chama layoutSubviews em a vista de ter a sua estrutura definida apenas Se o parâmetro de tamanho do quadro é diferente
  • rolagem um UIScrollView causas layoutSubviews a ser chamado em o scrollView, e sua superview
  • rotação de um dispositivo só chama layoutSubview sobre a vista principal (o viewControllers respondendo primária view)
  • Redimensionar uma vista chamará layoutSubviews em seu superview

Os meus resultados - http: // blog. logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/

Com base na resposta anterior por @BadPirate, eu experimentei um pouco mais longe e veio com alguns esclarecimentos / correções. Descobri que layoutSubviews: será chamado em uma visão se e somente se:

  • O seu próprio limites (não frame) alterado.
  • Os limites de um de seus subviews diretos alterado.
  • Um subexibição é adicionado à vista ou removido a partir da vista.

Alguns detalhes relevantes:

  • Os limites são considerados alterado apenas se o novo valor é diferente, incluindo uma origem diferente . Nota especificamente por isso layoutSubviews: é chamado sempre que um UIScrollView pergaminhos, como ele executa a rolagem alterando origem dos seus limites.
  • A alteração do quadro só vai mudar os limites se o tamanho mudou, pois esta é a única coisa propagadas para a propriedade limites.
  • Uma mudança na limites de uma visão de que ainda não está em uma hierarquia de vista resultará em uma chamada para layoutSubviews: quando a vista é eventualmente adicionado a uma hierarquia de exibição .
  • E apenas para ser completo: esses gatilhos não diretamente layoutSubviews chamada, mas setNeedsLayout em vez de chamadas, que define / levanta uma bandeira. Cada iteração do loop prazo, para todas as vistas na hierarquia vista , esta bandeira é verificado. Para cada visualização onde a bandeira é encontrado levantada, layoutSubviews: é chamado sobre ele e a bandeira é reposto. Visualizações mais acima na hierarquia serão verificados / chamado pela primeira vez.

https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5- SW1

mudanças de layout pode ocorrer sempre que qualquer dos seguintes eventos acontece em uma visão:

a. O tamanho dos limites de uma vista retângulo mudanças.
b. Uma mudança de orientação da interface ocorre, o que geralmente desencadeia uma mudança de limites da exibição de raiz retângulo.
c. O conjunto de subcamadas Core Animation associados com alterações na camada da vista e requer layout.
d. Suas forças aplicativo de layout para ocorrer chamando o setNeedsLayout ou layoutIfNeeded método de um ponto de vista.
e. Suas forças aplicativo de layout chamando o método setNeedsLayout de objeto da camada subjacente do ponto de vista.

Alguns dos pontos em resposta de BadPirate são apenas parcialmente verdadeira:

  1. Para o ponto addSubView

    addSubview provoca layoutSubviews a ser chamado no modo de exibição que está sendo adicionado, a visão que está sendo adicionado ao (exibição de destino), e todos os subviews do alvo.

    Depende (vista alvo) máscara autoresize da vista. Se ele tem autoresize máscara ON, layoutSubview será chamado em cada addSubview. Se ele não tem máscara autoresize então layoutSubview só será chamado quando (de destino Ver) tamanho mudanças quadro da vista.

    Exemplo:. Se você criou UIView programaticamente (não tem máscara autoresize por padrão), LayoutSubview será chamado somente quando UIView quadro não muda em cada addSubview

    É através desta técnica que o desempenho do aplicativo também aumenta.

  2. Para o ponto de rotação do dispositivo

    Rodar um dispositivo só chama layoutSubview na vista principal (a responder vista principal da viewController)

    Isso pode ser verdade apenas quando o VC está na hierarquia VC (root no window.rootViewController), bem este é caso mais comum. Em iOS 5, se você criar um VC, mas não é adicionado em qualquer outro VC, então este VC não iria obter qualquer notado quando rotate dispositivo. Portanto, sua visão não iria ser notado chamando layoutSubviews.

chamada [self.view setNeedsLayout]; em viewController torna a chamar viewDidLayoutSubviews

você olhou layoutIfNeeded?

O trecho de documentação está abaixo. Será que o trabalho de animação, se você chamar esse método explicitamente durante a animação?

layoutIfNeeded Estabelece os subviews se necessário.

- (void)layoutIfNeeded

Discussão Utilize este método para forçar o layout de subviews antes de desenhar.

Disponibilidade Disponível em iPhone OS 2.0 e posterior.

Ao migrar um aplicativo OpenGL do SDK 3-4, layoutSubviews não foi chamado mais. Depois de muita tentativa e erro eu finalmente abriu MainWindow.xib, selecionou o objeto Window, no Inspetor escolheu Janela Atributos guia (mais à esquerda) e marcada "Visível no lançamento". Parece que no SDK 3 é ainda usado para causar uma chamada layoutSubviews, mas não em 4.

6 horas de frustração put ao fim.

Uma vez obscurecer, caso ainda potencialmente importante quando layoutSubviews nunca é chamado é:

import UIKit

class View: UIView {

    override class var layerClass: AnyClass { return Layer.self }

    class Layer: CALayer {
        override func layoutSublayers() {
            // if we don't call super.layoutSublayers()...
            print(type(of: self), #function)
        }
    }

    override func layoutSubviews() {
        // ... this method never gets called by the OS!
        print(type(of: self), #function)
    }
}

let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top