Eu basicamente quero ter minhas subvisualizações posicionadas de maneira diferente dependendo da orientação do iPad (Retrato ou Paisagem) usando classes de dimensionamento introduzidas no xcode 6. Eu encontrei vários tutoriais explicando como diferentes classes de dimensionamento estão disponíveis para Iphones em retrato e paisagem no IB mas, no entanto, parece não haver nenhum que cubra modos individuais de paisagem ou retrato para o iPad no IB. Alguém pode ajudar?
objective-c
ios8
size-classes
adaptive-ui
neelIVP
fonte
fonte
Respostas:
Parece que a intenção da Apple é tratar as duas orientações do iPad como iguais - mas, como vários de nós estamos descobrindo, há razões de design muito legítimas para querer variar o layout da IU para iPad Retrato vs. iPad Paisagem.
Infelizmente, o sistema operacional atual não parece fornecer suporte para essa distinção ... o que significa que estamos de volta à manipulação de restrições de layout automático no código ou soluções alternativas para alcançar o que deveríamos idealmente conseguir gratuitamente usando Adaptive UI .
Não é uma solução elegante.
Não há uma maneira de aproveitar a magia que a Apple já incorporou ao IB e ao UIKit para usar uma classe de tamanho de nossa escolha para uma determinada orientação?
~
Ao pensar sobre o problema de forma mais genérica, percebi que 'classes de tamanho' são simplesmente maneiras de lidar com vários layouts armazenados em IB, para que possam ser chamados conforme necessário no tempo de execução.
Na verdade, uma 'classe de tamanho' é apenas um par de valores enum. De UIInterface.h:
Portanto, independentemente de como a Apple decidiu nomear essas variações diferentes, fundamentalmente, eles são apenas um par de números inteiros usados como uma espécie de identificador único, para distinguir um layout de outro, armazenado em IB.
Agora, supondo que criemos um layout alternativo (usando uma classe de tamanho não utilizada) em IB - digamos, para iPad Portrait ... há uma maneira de fazer com que o dispositivo use nossa escolha de classe de tamanho (layout de IU) conforme necessário no tempo de execução ?
Depois de tentar várias abordagens diferentes (menos elegantes) para o problema, suspeitei que poderia haver uma maneira de substituir a classe de tamanho padrão programaticamente. E há (em UIViewController.h):
Assim, se você pode empacotar sua hierarquia de controlador de visão como um controlador de visão 'filho', e adicioná-lo a um controlador de visão pai de nível superior ... então você pode sobrescrever condicionalmente o filho fazendo-o pensar que é uma classe de tamanho diferente do padrão do sistema operacional.
Aqui está um exemplo de implementação que faz isso, no controlador de visualização 'pai':
Como uma demonstração rápida para ver se funcionava, adicionei rótulos personalizados especificamente às versões 'Regular / Regular' e 'Compacto / Regular' do layout do controlador filho em IB:
E é assim que funciona, quando o iPad está nas duas orientações:
Voila! Configurações de classe de tamanho personalizado em tempo de execução.
Esperançosamente, a Apple tornará isso desnecessário na próxima versão do sistema operacional. Enquanto isso, essa pode ser uma abordagem mais elegante e escalonável do que mexer programaticamente com restrições de layout automático ou fazer outras manipulações no código.
~
EDIT (6/4/15): Por favor, tenha em mente que o código de exemplo acima é essencialmente uma prova de conceito para demonstrar a técnica. Sinta-se à vontade para adaptar conforme necessário para sua aplicação específica.
~
EDIT (24/07/15): É gratificante que a explicação acima pareça ajudar a desmistificar o problema. Embora eu não tenha testado, o código de mohamede1945 [abaixo] parece uma otimização útil para fins práticos. Sinta-se à vontade para testar e nos dar sua opinião. (Para fins de integridade, deixarei o código de exemplo acima como está.)
fonte
UITraitCollection
é otimizado o suficiente eoverrideTraitCollectionForChildViewController
raramente é chamado o suficiente para não ser um problema fazer a verificação de largura e criá-lo.Como um resumo da longa resposta de RonDiamond. Tudo que você precisa fazer é no seu controlador de visualização raiz.
Objective-c
Rápido:
Em seguida, no storyborad, use largura compacta para Retrato e largura normal para Paisagem.
fonte
- (UITraitCollection *)traitCollection
substituí em vez deoverrideTraitCollectionForChildViewController
. Além disso, as restrições devem corresponder às coleções de características, portanto, wC (hAny).O iPad tem o traço de tamanho 'regular' para dimensões horizontais e verticais, sem distinção entre retrato e paisagem.
Essas características de tamanho podem ser substituídas em seu
UIViewController
código de subclasse personalizado , por meio do métodotraitCollection
, por exemplo:Isso dá ao iPad as mesmas características de tamanho do iPhone 7 Plus. Observe que outros modelos de iPhone geralmente têm a característica de 'largura compacta' (em vez de largura regular), independentemente da orientação.
Imitar o iPhone 7 Plus dessa forma permite que esse modelo seja usado como um substituto para o iPad no Interface Builder do Xcode, que não reconhece personalizações no código.
Esteja ciente de que a visualização dividida no iPad pode usar características de tamanho diferentes da operação normal em tela cheia.
Essa resposta é baseada na abordagem adotada nesta postagem do blog , com algumas melhorias.
Atualização 02/01/2019: Atualizado para corrigir a barra de status oculta intermitente no cenário do iPad e possível atropelamento de características (mais recentes)
UITraitCollection
. Observe também que a documentação da Apple realmente não recomenda a substituiçãotraitCollection
, portanto, no futuro, pode haver problemas com essa técnica.fonte
traitCollection
propriedade seja somente leitura: developer.apple.com/documentation/uikit/uitraitenvironment/…A resposta longa e útil de RonDiamond é um bom começo para compreender os princípios, no entanto, o código que funcionou para mim (iOS 8+) é baseado no método de substituição
(UITraitCollection *)traitCollection
Portanto, adicione restrições no InterfaceBuilder com variações para Largura - Compacto, por exemplo, para a propriedade da restrição Instalada. Portanto, largura - qualquer será válido para paisagem, largura - compacto para retrato.
Para alterar as restrições no código com base no tamanho do controlador de visualização atual, basta adicionar o seguinte em sua classe UIViewController:
fonte
Quão diferente será o seu modo paisagem do que o modo retrato? Se for muito diferente, pode ser uma boa ideia criar outro controlador de visualização e carregá-lo quando o dispositivo estiver no modo paisagem
Por exemplo
fonte
Versão 5 do Swift. Funciona bem.
fonte
Código Swift 3.0 para solução @RonDiamond
fonte