Skip to main content

Uicollectionview Paging Indicator Forex


Implementamos um scroller horizontal com UICollectionView, personalizando as dimensões do layout do fluxo de coleta. Queríamos mostrar um indicador de paginação à esquerda e um indicador de paginação direto para dizer que há mais células para a esquerda ou para a direita. Para realizar isso, escrevemos o código abaixo no método, mas não está funcionando corretamente. O número máximo de células que pode ser mostrado é 5 (ou seja, o tamanho da página é 5). Esta solução está funcionando corretamente quando rolarmos lentamente, mas não funcionamos quando rolarmos muito rápido. Sugira como podemos conseguir isso. Perguntou Mar 19 14 em 7: 16Bryan Hansen UICollectionVer um tutorial de layout personalizado Para um projeto recente, eu precisava refatorar uma visão primária dentro do nosso aplicativo para iPad, então eu decidi aprender os prós e contras de UICollectionView (introduzido no iOS 6) e eu pensei Seria um bom tutorial para compartilhar. Meu projeto acabou por precisar de um UICollectionViewLayout personalizado, o que significava que eu precisava lidar com mais da lógica de layout do que se o Id usasse o UICollectionViewFlowLayout que a Apple oferece. No entanto, criar um layout personalizado permite muito mais flexibilidade de design, então é o que eu vou levar até aqui. Bem, percorra o processo passo a passo, cobrindo os principais conceitos de design de layout personalizado: no final, tenha um layout de pilha de fotos totalmente funcional como visto aqui. Mesmo se você estiver interessado em implementar um layout consideravelmente diferente do apresentado aqui, os conceitos fundamentais serão bastante semelhantes. Então, retroceda com sua bebida favorita e, em uma noite ou duas, você terá uma compreensão completa dos layouts personalizados. O projeto final está disponível no github. Este tutorial está focado no iPhone, mas se você quiser criar um projeto para o iPad, a maioria dos itens apresentados deve funcionar com mudanças mínimas. Uma vez que o seu projeto é criado, você terá um aplicativo iOS Bare-bones com um estoque UIViewController. Neste projeto, todo o conteúdo do nosso controlador de exibição caberá dentro da visão de coleção fornecida automaticamente. Se o seu design tiver outros elementos, como cabeçalho estático ou seções de rodapé, você deseja usar UIViewController com um UICollectionView como uma das suas submissões. Altere o cabeçalho do controlador de visualização para que ele subclasse UICollectionViewController em vez disso: você pode renomear o controlador de exibição para algo mais apropriado. Isso pode ser feito facilmente selecionando o nome da classe no código e escolhendo Editar gt Refactor gt Renomear. Você também deve atualizar o xib referenciado ao chamar initWithNibName: no delegado da sua aplicação para refletir a mudança de nome. Também precisamos alterar o xib associado a este controlador de exibição para que ele faça referência a UICollectionView em vez do estoque UIView agora. Selecione os controladores de visualização xib e, em seguida, abra o painel do inspector do lado direito se ainda não estiver aberto. Encontre um objeto de exibição de coleção na parte inferior do painel direito e arraste um novo para o painel secundário esquerdo sob a exibição que já existe. Agora, temos uma instância de Coleção, mas nossa visão antiga ainda está associada ao controlador. Vamos resolver isso. Selecione a Vista antiga no painel secundário esquerdo e exclua-a. Agora, controle-arrastar do Proprietário de Arquivos para a Vista da Coleção. Quando você solta, selecione a exibição na lista para designar a exibição de coleção como a visualização principal dos controladores de exibição. Agora é um ótimo momento para organizar nossos arquivos Xcode um pouco, antes de continuar adicionando mais arquivos de classe. Crie um novo grupo Xcode chamado View Controller e arraste o controlador de visualização e o xib associado a este grupo. Como bem estar criando nosso próprio layout completamente personalizado, precisamos criar uma subclasse de layout de Coleção que irá lidar com a lógica de layout de todas as suas submissões . No grupo View Controller, crie uma nova classe Objective-C chamada BHPhotoAlbumLayout, quais subclasses UICollectionViewLayoutNext, bem, faça algumas mudanças nos controladores de exibição xib para suportar nossa classe de layout personalizada. Selecione o controle de exibição xib novamente, então selecione a instância Coleção na sub-painel. No painel do inspector direito, selecione a guia Atributos e, em seguida, role para baixo até a seção Coleção. Nesta seção, altere o layout de Fluxo para Personalizado. Em seguida, insira BHPhotoAlbumLayout no campo de classe revelado. Eventualmente, é preciso acessar a instância deste layout do nosso controlador de visualização, então devemos criar uma saída de propriedade no código e conectá-la no xib. Na nossa view, a subclasse do controlador importa o cabeçalho BHPhotoAlbumLayout e adiciona uma propriedade privada como IBOutlet: Volte para o arquivo xib. Em Objetos. Expanda a Exibição da coleção, então controle-arrastar do proprietário dos arquivos para o layout do álbum de fotos. Neste ponto, se você executasse o aplicativo, mesmo que tenha feito tudo correto, você ainda estará olhando para um abismo preto, não muito reconfortante. Definir uma cor de fundo na visão de coleção é uma boa maneira de verificar se a exibição está configurada corretamente. No nosso controlador de visualização dentro do viewDidLoad, defina a cor de fundo da visualização: agora você pode ativar seu aplicativo e garantir que a visão de coleção esteja aparecendo como deveria. Você deve ver a cor de fundo cinza escuro que definimos, em vez do preto padrão. Em seguida, comece a trabalhar nas visões específicas que a nossa visão de coleção irá apresentar. UICollectionView e UITableView são realmente bastante semelhantes em alguns aspectos. Ambos usam um padrão de design de delegação para facilitar a navegação e a interação com uma coleção de visualizações (células), bem como garantir que o desempenho seja aceitável ao fornecer um meio para armazenar em cache e reutilizar esses pontos de vista. No entanto, enquanto o UITableView impõe alguns detalhes de seu design e layout visuais, os UICollectionViews não impõem qualquer tipo de design ou layout visual, permitindo muito mais personalização em relação à apresentação de seu conteúdo. Bem, personalize nossa lógica de apresentação em breve, mas primeiro, crie algumas visualizações reutilizáveis ​​para nossa visão de coleção. Isso é muito parecido com a criação de células personalizadas para um UITableView. Crie um novo grupo Xcode chamado View. Dentro deste grupo, crie uma classe Objective-C chamada BHAlbumPhotoCell que subclasse UICollectionViewCell. Por agora, mantenha as coisas simples e configure apenas uma cor de fundo nesta célula dentro do InitWithFrame: Agora que temos uma célula simples pronta para uso, teríamos alguns conceitos básicos da lógica de layout implementados. Bem, comece por declarar algumas propriedades que permitirão a personalização de vários aspectos do layout. Adicione as seguintes propriedades ao cabeçalho BHPhotoAlbumLayout: Define alguns padrões para esses valores para facilitar a cada consumidor do nosso layout. Uma vez que alguém poderia especificar o layout de sua visão de coleção em um arquivo xib (como fizemos) ou inicializá-lo diretamente no código, precisamos substituir os métodos init e initWithCoder:. Além disso, em vez de duplicar o código, crie um método chamado setup que será chamado por qualquer um destes. Adicione esses métodos à implementação BHPhotoAlbumLayout: agora estavam chegando à carne e às batatas da nossa lógica de layout. Precisamos substituir um punhado de métodos que computarão e retornarão informações de layout para a visão de coleção. Embora exista mais do que uma maneira de fazer isso, a abordagem recomendada pela Apples para layouts que se modificam com pouca freqüência e mantém centenas de itens (em vez de milhares) é calcular e armazenar em cache todas as informações de layout antecipadamente e, em seguida, acessar esse cache quando os pedidos de exibição de coleção isto. Se você gostaria de saber mais, confira a documentação das maçãs em Criar layouts personalizados. Bem, use um dicionário para armazenar todas as nossas informações de layout. A estrutura será a seguinte: Bem, crie um sub-dicionário para cada tipo de exibição e use o caminho do índice de cada visualização específica como a chave e seus atributos de layout como o valor associado. Então, no dicionário de nível superior, use o tipo específico de visão como nossa chave e o subdicionário que acabamos de criar como valor. Isso permite um acesso rápido aos atributos de layout de um tipo específico de exibição em um caminho de índice específico. Vamos adicionar o uso do botão chave para nossas células agora. Defina um NSString estático para o BHAlbumPhotoCell na parte superior da implementação BHPhotoAlbumLayout. Abaixo disso, adicione o dicionário de nível superior como uma propriedade privada. Agora temos tudo o que precisamos para implementar prepareLayout. Vamos fazer isso substituir prepareLayout na implementação BHPhotoAlbumLayout: a lógica aqui é realmente bastante direta. Primeiro, criamos alguns dicionários mutables. Então, para cada seção na visão de coleção, nós seguimos cada um de seus itens e criamos UICollectionViewLayoutAttributes com base no caminho de índice atual. Definimos o quadro para esses atributos de exibição e, em seguida, adicionamos esses atributos ao sub-dicionário. Uma vez que nós seguimos todas as nossas seções, definimos o sub-dicionário no dicionário de nível superior. No final, estabelecemos nossa propriedade de dicionário privado para o dicionário temporário que criamos aqui. Você pode ter notado que chamamos frameForAlbumPhotoAtIndexPath: o que ainda não escrevemos. Acho que devemos fazer isso. Adicione frameForAlbumPhotoAtIndexPath: para a implementação BHPhotoAlbumLayout: A moldura é calculada com base no caminho do índice passado. Primeiro, determinamos a linha e a coluna corretas para o item. Em seguida, determinamos a quantidade total combinada de espaçamento horizontal entre itens. Então, se tivermos mais de 1 coluna, dividimos o espaçamento total para chegar ao espaçamento para cada item. Agora, podemos calcular o deslocamento horizontal do nosso quadro. Observe que elevamos esse valor para que nosso quadro atinja pixels inteiros, garantindo que ele pareça nítido. Um detalhe sutil aqui é que devemos planar o valor neste momento, não na linha anterior, onde dividimos pelo número de colunas. Isso garante que os itens estejam espaçados corretamente enquanto atravessamos uma vez que arredondamos o valor após a multiplicação pela coluna. Em seguida, calculamos nosso deslocamento vertical e, em seguida, retornamos o quadro com base nas origens e no tamanho do item. Agora que nosso layout foi determinado, precisamos substituir os métodos que passarão de volta à visão de coleção quando necessário. A primeira substituição é o layoutAttributesForElementsInRect. Esse método precisa retornar todos os atributos de layout necessários para uma determinada área de conteúdo da visão de coleção. Uma vez que todos estavam lidando até agora com células, simplesmente precisamos descobrir quais células se enquadram dentro dele. Isso é bom e fácil agora que temos todos os nossos atributos de layout prontos no nosso dicionário layoutInfo. Substitua layoutAttributesForElementsInRect: no BHPhotoAlbumLayout da seguinte maneira: Começamos criando uma matriz mutable onde podemos armazenar todos os atributos que precisam ser retornados. Em seguida, iriam tirar proveito da enumeração de dicionário baseado em bloco agradável para cruzar através do nosso dicionário layoutInfo. O bloco externo itera através de cada sub-dicionários que adicionamos (apenas as células no momento), então nós iteramos através de cada célula no sub-dicionário. CGRectIntersectsRect torna simples verificar se a célula estava olhando intersecções com a reta que foi passada. Se isso acontecer, nós a adicionamos à matriz bem passando de volta. O próximo método que precisamos implementar é ainda mais fácil devido ao mecanismo de cache que adotamos. Substituir layoutAttributesForItemAtIndexPath: em BHPhotoAlbumLayout da seguinte maneira: Todos estavam fazendo aqui pesquisando o sub-dicionário para células e, em seguida, retornando os atributos de layout para uma célula no passado no caminho do índice. Não pode ser mais simples O último método que precisamos substituir para que nosso layout esteja funcionando precisa retornar o tamanho geral do conteúdo para todo o nosso conteúdo. Substituir collectionViewContentSize: em BHPhotoAlbumLayout da seguinte maneira: Isso calcula e retorna o tamanho total necessário para mostrar tudo na nossa visão de coleção. A altura é baseada no número total de linhas e a largura é simplesmente a largura da própria visão de coleção. Com os conceitos básicos de nosso layout completo, agora precisamos retornar algum conteúdo válido dos métodos de fonte de dados na nossa subclasse de controle de exibição. Antes de devolver as células à nossa visão de coleção, primeiro precisamos designar nosso controlador de visualização como fonte de dados e delegar para nossa visão de coleção. Abra o xib associado ao nosso controlador de visualização e arraste o controle da Coleção para o proprietário dos Arquivos. Clique na saída dataSource e depois repita novamente para configurar a saída delegada. No nosso cabeçalho do controlador de exibição declara que ele implementa o protocolo para UICollectionViewDataSource e UICollectionViewDelegate. Now iriam registrar nossa classe de celular com a visão de coleção. Isso diz à coleção ver o que deveria estar pedindo. Isso requer um identificador para a célula. Mude para a nossa implementação do controlador de visualização e importe BHAlbumPhotoCell. h e defina uma string para o identificador da célula: Agora, no final do viewDidLoad no nosso controlador de visualização, registre a classe da célula para o identificador que definimos: Em seguida, precisamos implementar três métodos de fonte de dados Que parecerá familiar para aqueles que trabalharam com o UITableView antes. Implementar numberOfSectionsInCollectionView: no nosso controlador de visualização: Agora, simplesmente, devolva um número estático, então obtenha um conteúdo real funcionando em breve. Em seguida, implemente numberOfItemsInSection: no nosso controlador de visualização: Em seguida, implemente collectionView: cellForItemAtIndexPath: no nosso controlador de visualização: Tudo bem, finalmente é hora de disparar o Simulator e ver se nosso layout está funcionando. Se você fez as coisas bem, você deve ver um grupo de quadrados cinzentos em 2 colunas, que você pode percorrer verticalmente. Agora estavam chegando em algum lugar. Tudo bem, as coisas parecem ótimas até agora, mas você tentou girar seu dispositivo para a paisagem e não era exatamente o que estava procurando. Em vez de mostrar 2 colunas e um monte de espaço não utilizado à direita, é melhor mostrar 3 colunas quando estiverem na paisagem. Vamos fazer isso acontecer Override willRotateToInterfaceOrientation: duração: no nosso controlador de visualização: Primeiro, verificamos se o dispositivo está em Paisagem e, em caso afirmativo, definimos o número de colunas em 3 e, em seguida, ajuste o itemInsets um pouco para tornar as coisas uniformemente espaçadas. Se estivéssemos em Retrato, definimos as colunas em 2 e usamos os mesmos valores que definimos por padrão em nosso layout. Vamos dar um giro, disparar o seu aplicativo O que dá Por que não obtivemos o layout que especificamos Além disso, se você tentar rolagem, as coisas agem estranhamente. A questão é que nossos atributos de layout não foram atualizados para refletir o novo estado de nossa visão. Isso destaca uma das tarefas que devemos fazer quando as mudanças são feitas, que afetam o layout dos itens na nossa visão de coleção. Precisamos invalidar o layout, o que fará com que todos os nossos atributos de layout sejam recalculados. Isso é feito chamando invalidateLayout na instância UICollectionViewLayout e deve acontecer sempre que qualquer uma das propriedades personalizadas que adicionamos à nossa alteração de layout. Para fazer isso corretamente, devemos implementar explicitamente os setters para essas propriedades e invalidar o layout também. Implementar setters para cada uma das propriedades personalizadas em BHPhotoAlbumLayout: Cada setter primeiro verifica se o valor que está sendo definido é idêntico ao que já está definido e retorna se for esse o caso. Se for diferente, ele define a variável de instância e invalida o layout. Execute seu aplicativo agora, ele deve se comportar como esperado quando você gira o dispositivo. Com o nosso layout vindo muito bem, vamos colocar um pouco de esforço para obter algum conteúdo real para exibir. Estes quadrados cinzentos são agradáveis ​​e todos, mas o que realmente queremos ver são algumas fotos extravagantes. Para facilitar o fornecimento de fotos na nossa visão de coleção, precisariam algumas aulas para representá-las. Estes são considerados parte do modelo, dentro da organização conceitual Model-View-Controller do nosso aplicativo. Como o foco deste tutorial está em Coleção, as visualizações não vão passar muito tempo nas classes modelo. Normalmente, você usaria algo como o CoreData ou outra solução de armazenamento persistente para lidar com esse aspecto do seu aplicativo. Para este tutorial, basta baixar as classes do modelo e depois adicioná-las ao seu projeto. Crie um grupo chamado Modelo. Então arraste arquivos para BHPhoto e BHAlbum para o grupo. Certifique-se de que a caixa esteja marcada para o seu aplicativo em Adicionar aos destinos e se você estiver arrastando os arquivos de um local fora dos arquivos do projeto, certifique-se de que Copiar itens na pasta de grupos de destino também esteja marcado. Essas classes são bastante diretas. BHPhoto tem um URL e imagem em miniatura para uma foto. BHALbum tem um nome e uma série de fotos e a capacidade de adicionar ou remover uma foto. Agora, podemos criar alguns álbuns e adicionar uma foto a cada um para que possamos ter um pouco mais de interesse em mostrar. No topo da nossa implementação do controlador de visualização, importe BHAlbum. h e BHPhoto. h. Em seguida, crie uma propriedade de matriz mutável privada para armazenar todos os álbuns: então, dentro do método viewDidLoad no nosso controlador de visualização, adicione o seguinte depois de definir a cor de fundo na visão de coleção: essas fotos são carregadas do repositório GitHub para este projeto e São algumas das minhas fotos favoritas que eu tomei nos últimos anos. Nós também precisamos atualizar os métodos de exibição de dados de coleção no nosso controlador de visualização para que as contagens corretas de seção e item sejam retornadas. Tudo bem, temos alguns álbuns de fotos com algumas fotos, cada uma pronta para usar. Agora precisamos atualizar nossa célula de fotos para que ela possa exibi-las. Adicione uma propriedade UIImageView somente ao cabeçalho BHAlbumPhotoCell e redefini-lo como readwrite na implementação: Isso segue a convenção que a Apple usa para submissões no UITableViewCell, permitindo que os consumidores dessa classe mudem as propriedades da visualização de imagem fornecida, mas não alterem a Visualização de imagem em si. Em seguida, configure a imagem e outras estética em nossa célula. Para puxar alguns dos looks desejados, mudariam algumas propriedades em nossa camada de backup de células. Para fazer isso precisamos importar o framework QuartzCore. Adicione a importação no topo da implementação BHAlbumPhotoCell: em seguida, atualize initWithFrame: em BHAlbumPhotoCell para a correspondência, a seguir: Estabeleceu algumas propriedades diferentes em nossa camada de células para dar uma boa sombra e afetar a borda. Também criamos uma instancia em nossa visão de imagem, definimos algumas propriedades para sua exibição e, em seguida, adicione-a como uma subvisão do conteúdo de células. O último bit de trabalho que precisamos fazer em nossa célula é override prepareForReuse e restaure qualquer imagem que possa ter sido definida no imageView. Isso garante que nossas células parecem frescas mesmo quando elas são reutilizadas pelo collectionView. Adicione prepareForReuse para BHAlbumPhotoCell: precisamos chamar de super quando substitui este método para que a célula seja configurada corretamente antes de ser reutilizada. Doce, agora podemos definir uma imagem na nossa célula fotográfica. Na nossa atualização do controlador de exibição, coleteView: cellForItemAtIndexPath: para corresponder o seguinte: Aqui pegamos o álbum para esta seção e depois a foto para este item. Uma vez que possamos, podemos definir a imagem das fotos na célula. Aumente o seu aplicativo e veja o que obtém Depois que as fotos terminarem de carregar, elas devem estar visíveis na visão de coleção. Falando em carregar, você percebeu quanto tempo demorou para ver essas fotos. Nós essencialmente fundamentamos a capacidade de resposta de nossas aplicações, já que agora nossos usuários esperam que todas as fotos visíveis sejam carregadas antes que elas possam ver ou interagir com qualquer coisa. Isso não vai cortá-lo. Vamos refatorar nosso controlador de visualização para que as fotos sejam carregadas em segundo plano e não na fila principal. Existem algumas abordagens diferentes que podemos tomar aqui, mas escolhi usar um NSOperationQueue baseado em bloco, o que nos permite definir prioridades para as operações que realizamos. Primeiro, precisamos adicionar uma propriedade privada para a fila de operação no topo do nosso controlador de visualização. Agora, inicialize o NSOperationQueue e configure-o em nossa propriedade. Uma vez que nossas operações são completamente independentes uma da outra, bem, também, configure o número máximo de operações simultâneas que pode realizar em 3, o que tornará as coisas ainda mais rápidas. Adicione essas linhas à parte inferior do viewDidLoad no nosso controlador de exibição. Em seguida, onde anteriormente carregámos a imagem da foto diretamente cada vez que carregamos uma célula, então coloque a fila de operação para que ela seja carregada em segundo plano. Substitua a antiga implementação do collectionView: cellForItemAtIndexPath: no nosso controlador de visualização com o seguinte: Não seja intimidado por toda a concorrência, operações, despachos e o que não aconteça aqui, talvez um pouco intimidado, mas apenas porque pode ser complicado para programadores avançados também. Tudo estava fazendo criar uma NSBlockOperation com um bloco de código que será executado mais tarde pelo NSOperationQueue. Por estarem fazendo referência ao auto dentro do bloco, também precisamos criar uma referência fraca para usar. Esta configuração completa permitirá que a nossa interface de usuário permaneça receptiva aos nossos usuários. Quando o bloco é executado, primeiro carrega a imagem da foto como fazíamos anteriormente. Então, através do Grand Central Dispatch, enviamos de forma assíncrona algum trabalho de volta para a fila principal para configurar a imagem em nossa célula de foto. Isso é necessário porque qualquer coisa que toca a UI precisa ser executada na fila principal. Por razões de desempenho, apenas definiram a imagem se a célula estava trabalhando ainda está em exibição, dessa forma, se o usuário estiver rolando muito rápido, não vamos desacelerar definindo imagens que eles nem verão. Um último detalhe é porque o A imagem pode terminar de carregar um tempo depois da chamada original para cellForItemAtIndexPath: não devemos confiar no photoCell que foi desativado para ser a célula atual para nosso caminho de índice mais. Pode já ter sido reutilizado se o usuário continuasse a rolar. Em vez disso, nós re-obter a célula com base no caminho do índice e, em seguida, definir a imagem na exibição de imagem das células. (Uma nota lateral, se o nosso aplicativo permitisse aos usuários adicionar, remover ou reorganizar fotos, não poderíamos assumir que o caminho do índice original ainda é válido, em vez disso, também precisamos procurar isso novamente com base no álbum específico e Foto.) Com o NSBlockOperation criado bem agora, adicione a operação à nossa fila, que tratará a execução do bloco para nós. Vamos dar uma corrida e ver como ela é executada. As imagens devem estar sendo carregadas com visibilidade mais rápida agora que 3 estão carregando ao mesmo tempo e a rolagem deve ser suave. Bom trabalho Agora que temos uma foto carregada para cada álbum, vamos até a ante e conseguimos uma pilha inteira de fotos carregando e olhando nítido. Para fazer isso, você aproveitaria algumas outras propriedades em UICollectionViewLayoutAttributes. Além de configurar o quadro, também podemos definir valores para transform3D, alpha, zIndex, escondidos. Se esses não forem suficientes, você pode criar uma subclasse e adicionar propriedades personalizadas também, embora eu não cubra isso aqui. Para alcançar o empilhamento, a aparência estava indo para bem estar usando transform3D e zIndex. Conceitualmente, o que queremos ter são fotos empilhadas de cima para baixo em cada seção com cada foto com uma ligeira rotação aplicada. Isso combinado com a sombra de camadas que já adicionamos à célula é tudo o que é necessário fazer com que pareça agradável. Em primeiro lugar, lide com a rotação. Queremos que as rotações em cada foto pareçam um tipo de casual e natural, como se alguém simplesmente as deixasse cair sobre uma mesa. Bem, gerar algumas rotações aleatórias para conseguir isso, mas a única tentativa é que precisamos dessas rotações para permanecerem consistentes uma vez que foram geradas para que possamos recarregar células sem que elas mudem de forma inesperada. Para fazer isso, bem, gere um conjunto de rotações quando criamos o nosso layout e, em seguida, adotemos o uso deles de forma previsível através do uso de uma constante. Declare essas constantes abaixo, onde você importa seus cabeçalhos no topo da implementação BHPhotoAlbumLayout: então crie uma propriedade de matriz privada na implementação BHPhotoAlbumLayout também: vamos carregar essa matriz com algumas rotações CATransform3D, mas precisamos importar a estrutura QuartzCore Em nosso projeto primeiro para que isso funcione. Selecione seu arquivo de projeto e selecione a guia Construir Fases na parte superior da coluna do meio. Expanda a seção Binário de links com bibliotecas e aperte o botão no canto inferior esquerdo. Encontre o QuartzCore. framework e adicione-o ao seu projeto: Em seguida, adicione o seguinte no final do método de configuração em BHPhotoAlbumLayout: Primeiro criamos uma matriz mutável temporária à qual adicionamos objetos. Então, percorremos nosso loop, criando uma rotação de cada vez. Criamos uma porcentagem aleatória entre -1.1 e 1.1 e, em seguida, usamos isso para criar um CATransform3D ajustado. Eu geeked um pouco e adicionei alguma lógica para garantir que a porcentagem de rotação que geramos aleatoriamente é pelo menos 0,6 diferente da gerada de antemão. Isso garante que as fotos em uma pilha não tenham o infortúnio de que todos sejam girados da mesma maneira. Uma vez que temos nossa transformação, adicionamos-a à matriz temporária envolvendo-a em um NSValue e depois enxaguar e repetir. Depois que todas as 32 rotações são adicionadas, estabelecemos nossa propriedade de matriz privada. Agora precisamos colocar isso para uso. Eu optei por configurar a transformação em nosso UICollectionViewLayoutAttributes de forma semelhante à forma como definimos seu quadro, através do uso de um método de auxiliar privado. Adicione o seguinte método para a parte inferior da implementação BHPhotoAlbumLayout: Utilizamos a constante de passo que declaramos anteriormente para saltar alguns valores de rotação entre as seções. Isso nos permite obter nossos valores de dinheiro a partir da matriz de rotações, ao compensar a partir da primeira rotação na matriz com base na seção e no item do caminho de índice passado. Então modificamos esse deslocamento pelo RotationCount para garantir que permaneçamos dentro dos limites das arrays. Por ter escolhido inteligentemente um passo de 3 e uma contagem de rotação total de 32, você notará que, se acabarmos de ter muitas seções, aproveite de forma eficiente todas as rotações na matriz como um deslocamento inicial, disfarçando otimamente o fato de que usamos valores de rotação repetidos . Agora, precisamos configurá-los em nossos atributos de layout. Agora, prepareLayout. Diretamente abaixo, onde estabelecemos o quadro em nosso UICollectionViewLayoutAttributes, vamos configurar o transform3D usando nosso método de transformForAlbumPhotoAtIndex: vamos dar um giro e ver o que recebemos. Tudo bem, temos uma variedade de rotações aplicadas às nossas fotos, no entanto, você pode ter notado que as bordas do quadro ficam um pouco irritadas. Isso pode ser corrigido ao solicitar a camada de células para rasterizar. Atualize o método initWithFrame: no BHAlbumPhotoCell, adicionando 2 novas linhas: agora, devemos ver algumas fotos rodadas suavemente em nossa visão. Heck, agora que nós conseguimos que nossas fotos girassem bem, vamos piscar o número em cada seção para ver uma ação de empilhamento doce e doce. Em viewDidLoad no nosso controlador de visualização, atualize o início do loop interno para aumentar o número de fotos em Cada seção: depois de aumentar o número de fotos, você notou alguma diferença no tempo de carregamento das imagens. É verdade, temos mais imagens para carregar, mas também nos preocupamos mais com a foto superior em cada pilha do que aquelas abaixo . Que tal nós conseguimos isso para carregar à frente dos outros. Uma das razões pelas quais eu escolhi um NSOperationQueue como o meu meio de carregar as fotos de forma assíncrona é porque podemos especificar um nível de prioridade para cada operação que criamos. Usando isso, podemos simplesmente elevar a prioridade de carregar a foto superior em cada seção. Em collectionView: cellForItemAtIndexPath: no nosso controlador de exibição, defina a prioridade do NSBlockOpertation antes de adicioná-lo à fila: para o item superior, estabelecemos a prioridade para alto, os outros que definimos como normais. Vamos executar o aplicativo novamente e ver se isso melhorou nosso tempo de carregamento. Hmm, isso não parece fazer muita diferença. Talvez a prioridade do carregamento não seja a única questão que enfrentou. De fato, mudar as prioridades de nossas tarefas de operação é apenas metade da batalha. Nós também precisamos garantir que o que consideramos ser a melhor foto é realmente colocado no topo da nossa visão. Para fazer isso precisamos especificar o zIndex de nossas células corretamente. O zIndex determina se uma célula está acima ou abaixo de outra célula. Por padrão, todas as nossas células possuem um zIndex de 0, o que significa que sua ordem é completamente arbitrária. Uma vez que podemos ter uma quantidade variável de células em cada seção, use um valor base para o nosso zIndex e, em seguida, aumente-a com base em quão alto na pilha a célula deve aterrar, sendo o item superior o mais alto. Adicione uma constante de número inteiro na parte superior da implementação BHPhotoAlbumLayout: Em seguida, preparepayout em BHPhotoAlbumLayout configure o zIndex nos atributos da camada: Execute seu aplicativo para confirmar que voltou a carregar as fotos rapidamente. Tudo bem, estava fazendo progresso, apenas algumas coisas mais para trabalhar antes de termos um navegador de álbum de fotos totalmente projetado. Todas essas ótimas fotos são fáceis nos olhos, mas esse design também exige que o nome do álbum seja mostrado abaixo de cada pilha de fotos. Para facilitar a adição deste título à nossa visão de coleção, iriam introduzir outro tipo de exibição na mistura. As visualizações da coleção podem conter até três tipos de subclasses de exibição reutilizáveis ​​em seu layout: células (que usamos para nossas pilhas de fotos), visualizações suplementares e visões de Decoração. Se a sua vista requer qualquer tipo de dados do controlador de exibição para exibir, então você precisa usar as Cópias ou as visualizações suplementares. As visões de decoração, por outro lado, são principalmente para fins estéticos e não devem usar dados do controlador de visualização. Uma vez que nossas visualizações de título exibirão o nome de cada álbum, precisamos usar vistas suplementares para estes. A maior parte do trabalho bem feito será muito semelhante à configuração que fizemos para nossas células. Comecemos pela modificação do nosso layout para criar espaço para os títulos dos álbuns. Para fazer isso precisamos adicionar mais espaço vertical entre a parte inferior de uma pilha e o início da mesma abaixo. Em vez de tornar a altura fixa e inflexível, vamos adicionar uma propriedade que permita aos consumidores da nossa classe de layout definir o próprio altura. No cabeçalho BHPhotoAlbumLayout, adicione uma propriedade para titleHeight: Mais uma vez, é preciso invalidar o nosso layout se essa propriedade for alterada, portanto, implemente explicitamente o setter para a altura do título: Adicione o seguinte abaixo aos outros métodos de setter em BHPhotoAlbumLayout: Vamos também configurar um Padrão sensato para esta propriedade dentro do método de configuração: também iria precisar de outra cadeia de caracteres exclusivo para a exibição de título estava prestes a adicionar. Uma vez que as visualizações de Suplementação e Decoração precisam de uma cadeia de caracteres para registro, vamos tornar esta seqüência de caracteres pública para que possamos usá-la para registro, bem como no dicionário de layout. Defina um NSString na parte superior do cabeçalho BHPhotoAlbumLayout e configure-o na implementação: dividir a definição e a configuração garante que os consumidores usem a constante e não o valor específico. Em seguida, precisamos criar atributos de layout para cada exibição de título dentro do prepareLayout. Isso exigirá a adição de outro sub-dicionário para que possamos armazenar nossos atributos de layout de títulos da mesma maneira que fizemos para nossas células. At the beginning of prepareLayout on BHPhotoAlbumLayout create another dictionary:Now, since we only need one title per section, lets add it at the same time were adding attributes for the first cell, conveniently using the index path we already have on hand. Update the inner-loop on prepareLayout to match the following:Notice that we need to supply the kind when creating the layout attributes for Supplementary views. This can be used to differentiate Supplementary views used in your layout that happen to use the same class, but require different layout attributes. (Imagine if we also wanted to have a smaller subtitle below the album name telling users how many photos are in the album. We could use the same view class, but we might want to use a decreased height) For our view we only have one type of supplementary view. Finally, we need to set the titleLayoutInfo sub-dictionary on the top level dictionary: Add the following towards the end of prepareLayout. right after setting the cellLayoutInfo on newLayoutInfo:Since were once again calling a private helper method to obtain the frame for our title, we need to go implement that as well. After the other existing frame helper method add frameForAlbumTitleAtIndexPath:Calculating the frame for our title is a bit simpler since we can just base it off the frame of our cells. We do however need to update our cell frame and total content size calculations to take account for the added height of the titles. Update frameForAlbumPhotoAtIndexPath: to take account of the title height when calculating originY : Also, update the height calculation on collectionViewContentSize: to take account of the title height:The last thing we need to do is override the method which obtains layout attributes for a supplementary view at a specific index path. Add the following method on BHPhotoAlbumLayout below where we do this for our cells already:Thats all we need to update on our layout to handle album titles. Because of how weve structured our layoutInfo cache, no changes are necessary for layoutAttributesForElementsInRect: to correctly handle this additional view. If you run the app now, youll see that extra height has been added between each stack. Next we need to create a class for our album title views. Before we had subclassed UICollectionViewCell, but that class is used only for cells of a collection view. For supplementary views we need to subclass UICollectionReusableView. Create a class within the View grouping called BHAlbumTitleReusableView which subclasses UICollectionReusableView. This title view will be pretty basic, well just add one label, giving us a place to set our album name. Create a readonly property called titleLabel to the header of BHAlbumTitleReusableView and then re-define it as readwrite in its implementation:Now well setup our label on the view. Unlike cells where we need to add subviews to the contentView . here we add them directly on the view. Update initWithFrame: on BHAlbumTitleReusableView to the following:We also need to be sure to reset the labels text whenever the view is reused. Override perpareForReuse on BHAlbumTitleReusableView :Alright weve got some titles, before we can use them we need to define a reuse identifier and register them with the collection view. At the top of our view controller implementation define a static NSString for the identifier: Next, import the BHAlbumTitleReusableView header at the top of our view controller implementation. Then add the following towards the end of viewDidLoad :Now well implement another data source method and return instances of BHAlbumTitleReusableView when the collection view asks for them. Add collectionView:viewForSupplementaryElementOfKind:atIndexPath: to our view controller:Theres nothing special going on here, we get the album for this section and set its name on our title views label. Alright, now lets see how our app is looking BOOM Weve got title labels, this thing is really starting to come together. Now that everything is laid out nicely, lets make the view a little more visually interesting by swapping out the dull gray background color for a nice subtle textured look. A great website for finding textures which arent visually overbearing is subtlepatterns. They have dozens of textures in both normal and retina sizes. I found this concrete wall texture to work great. Create a new group named Images within the existing Supporting Files group. Download a texture you like and then add the image files to the Images group. We can easily add a background texture to our collection view by creating a UIColor with a pattern image. In viewDidLoad on our view controller subclass update the background color we set on the collection view to use a pattern:At this point I think weve got a pretty good looking view, but Id also like to walk through how to add decoration views. Although this may be bit contrived, what were going to do now is add a small emblem decoration tucked up above the photo stacks. Its something youll only see when pulling down on the view before it snaps back into place, but its a good way to show how to work these kinds of views in because they may be more beneficial in other layout designs. Now that weve added cells and supplementary views, this will feel somewhat familiar. The primary difference is that our collection views data source wont need to be involved with the logic of the emblem view. The layout and the emblem view itself will handle everything on their own. Create a class named BHEmblemView as a subclass of UICollectionReusableView within the View group. For this view, were just going to display the same image all the time and this can easily be done within initWithFrame: on our emblem view. If you wanted to create a more customizable decoration view, you would need to make use of custom properties, which requires creating a subclass of UICollectionViewLayoutAttributes and then setting those up within the layout. You can use the image I used or use your own. Were also going to create a simple class method to return the size of the image so that we can provide this to our layout class without needing to instantiate an emblem view. Add a class method named defaultSize to the BHEmblemView header: Switch to the implementation of BHEmblemView and add a constant for the image name: Then implement defaultSize :Now well set up the view to display our emblem. Update initWithFrame: on BHEmblemView to match the following:The collection view will handle instantiation of the emblem view using the frame which well set on its layout attributes. Unlike cells and supplementary views, decoration views are registered with the layout rather than the collection view. Import the BHEmblemView header into the BHPhotoAlbumLayout implementation. Define another kind string for our emblem at the top of the BHPhotoAlbumLayout : Register the emblem view at the end of the setup method on BHPhotoAlbumLayout :Unlike the other views weve added, only the layout class deals with decoration views, thus we perform the registration here rather than in the view controller. Now lets create another private frame helper method for our emblem. Add frameForEmblem towards the bottom of BHPhotoAlbumLayout :Here we get the default size for our emblem and then calculate an origin that will place the view centered horizontally and ending 30pts above the very top of the collection view and pass it back. Now that we have our frame, were ready to create some layout attributes for the emblem. Since were only going to have one emblem, we can create our attributes before we loop through all the sections and rows. Once again, well create a sub-dictionary and add it to the layoutInfo dictionary. Update prepareLayout to match the following:The last step is to return layout attributes for a decoration view with a given kind at a given index path. Add layoutAttributesForDecorationViewOfKind:atIndexPath: to BHPhotoAlbumLayout :Thats all we need to do for the emblem. If you fire up the app and pull down on the view, you should see the emblem tucked above. This covers the fundamental steps of creating custom layouts with UICollectionView. I hope its been enlightening From this point you could consider implementing custom animations for adding, deleting or moving items. Maybe it would be cool to tap a stack and have it expand out into a more detailed view for that album. If theres a lot of interest I may consider covering more advanced topics in an additional tutorial. Although I dont have a comments section here, feel free to email me any feedback regarding this tutorial at bryanehansengmail . copy 2012 Bryan Hansen

Comments

Popular posts from this blog

International Forex Trading Company Chipre Feriados

Negociação a partir dos Gráficos Um dos benefícios da negociação na FXCMs Trading Station é a capacidade de negociar diretamente a partir de gráficos. Neste vídeo, mostramos como colocar os negócios de forma rápida e fácil. O Trading Station Desktop permite que você troque diretamente dos gráficos. A colocação de pedidos de mercado é tão simples como clicar com o botão direito do mouse em um gráfico e selecionar Criar uma ordem de mercado. A colocação de pedidos de entrada pode ser feita da mesma forma ou você pode clicar com a mão esquerda em um preço do eixo Y. Editar o preço do pedido é feito clicando e arrastando a ordem para um novo local. Se você precisa fechar um negócio ou cancelar um pedido, basta clicar no pedido e confirmar a solicitação clicando em OK. A negociação de gráficos realmente simplifica o processo de negociação. Vídeos educacionais: todos os vídeos são fornecidos apenas para fins educacionais e os clientes não devem confiar no conteúdo ou políticas, pois podem di...

Best Books To Learn Stock Options

APRESENTANDO A MELHOR OPÇÃO TRADING LIVROS Obrigado por seu interesse em seu sucesso financeiro - Na verdade, uma das características de todas as pessoas bem sucedidas é o seu grande interesse em ler livros úteis e relevantes. Eu também, devo atribuir meu sucesso atual em grande parte com uma enorme linha dos melhores livros de troca de opções que eu li ao longo do caminho. Aqui, você encontrará os livros de troca de opções que eu li e o nível de conhecimento de negociação de opções de que são relevantes para que você não tenha que pesquisar novamente a pilha de feno para a agulha dourada. --- Jason Ng. Chief Option Strategist, Masters O Equity Asset Management Você é um iniciante quando ouviu falar sobre negociação de opções, mas nunca teve qualquer curso de negociação de opções, nem iniciou a negociação de opções de forma real ou começou a negociar opções, mas não tem ideia de como Tudo isso realmente funciona. Esses livros de negociação de opções irão ensinar-lhe o que é a negociaçã...

Guide Du Forex

Apprenez trader sur le Forex Obtenha o guia de negociação sobre o Forex para os advogados. Este guia é um incentivo para a aquisição de dinheiro. Saiba mais sobre o Forex e os comerciantes do Forex. Os benefícios do Forex e o comentário sobre difusão de tradições. Quatre tapes simples pour placer votre premier Trade sur le Forex As três qualificações não são necessárias para se tornar um comerciante no Forex Compte Dmo: bem que as contas de demonstração tentam reproduzir as marchas em condições, em um ambiente de março em simulação. Assim, é diferente de contas, por exemplo do fato de falta de correlação com a liquidação do mercado em rel, de dlais ao nível das cotações, e da disponibilidade de certos produtos por parte dos relatos. Por favor, note-se que a capacidade de transformação das informações sobre uma conta pode ser atraente de transações atípicas, expõe sem restrições, assim como a questão dos problemas e a devolução da derrapagem. É possível que você obtenha galões e queixas...