Eu tenho uma camada com algum código de desenho complexo em seu método -drawInContext:. Estou tentando minimizar a quantidade de desenho que preciso fazer, portanto, estou usando -setNeedsDisplayInRect: para atualizar apenas as partes alteradas. Isso está funcionando esplendidamente. No entanto, quando o sistema gráfico atualiza minha camada, ele está mudando da imagem antiga para a nova imagem usando um cross-fade. Eu gostaria que mudasse instantaneamente.
Eu tentei usar o CATransaction para desativar ações e definir a duração como zero, e nenhum trabalho. Aqui está o código que estou usando:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
Existe um método diferente no CATransaction que eu deveria usar (também tentei -setValue: forKey: with kCATransactionDisableActions, mesmo resultado).
iphone
ios
core-animation
calayer
Ben Gottlieb
fonte
fonte
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
Respostas:
Você pode fazer isso definindo o dicionário de ações na camada para retornar
[NSNull null]
como uma animação para a chave apropriada. Por exemplo, eu usopara desativar as animações de desvanecimento / desbotamento na inserção ou alteração de subcamadas em uma das minhas camadas, bem como alterações no tamanho e no conteúdo da camada. Acredito que a
contents
chave é a que você está procurando para evitar o crossfade no desenho atualizado.Versão rápida:
fonte
@"position"
tecla@"hidden"
propriedade no dicionário de ações se você estiver alternando a visibilidade de uma camada dessa maneira e desejar desativar a animação de opacidade.actionForKey:
vez), descobrindofontSize
,contents
,onLayout
ebounds
. Parece que você pode especificar qualquer chave que possa usar nosetValue:forKey:
método, especificando caminhos de chave complexos comobounds.size
.Além disso:
fonte
//foo
por[self setNeedsDisplayInRect: rect]; [self displayIfNeeded];
para responder à pergunta original.[CATransaction setDisableActions:YES]
[CATransaction setDisableActions:YES]
é uma abreviação para apenas a[CATransaction setValue:forKey:]
linha. Você ainda precisa das linhasbegin
ecommit
.Quando você altera a propriedade de uma camada, a CA geralmente cria um objeto de transação implícito para animar a alteração. Se você não deseja animar a alteração, pode desativar animações implícitas criando uma transação explícita e configurando sua propriedade kCATransactionDisableActions como true .
Objetivo-C
Rápido
fonte
Além da resposta de Brad Larson : para camadas personalizadas (criadas por você), você pode usar a delegação em vez de modificar o
actions
dicionário da camada . Essa abordagem é mais dinâmica e pode ter melhor desempenho. E permite desabilitar todas as animações implícitas sem precisar listar todas as chaves animáveis.Infelizmente, é impossível usar
UIView
s como delegados de camadas personalizadas, porque cadaUIView
um já é um delegado de sua própria camada. Mas você pode usar uma classe auxiliar simples como esta:Uso (dentro da vista):
Às vezes, é conveniente ter o controlador do view como um representante das subcamadas personalizadas do view; Nesse caso, não há necessidade de uma classe auxiliar, você pode implementar o
actionForLayer:forKey:
método dentro do controlador.Nota importante: não tente modificar o delegado da
UIView
camada subjacente (por exemplo, para ativar animações implícitas) - coisas ruins acontecerão :)Nota: se você deseja animar (e não desativar a animação para) redesenhos de camadas, é inútil colocar uma
[CALayer setNeedsDisplayInRect:]
chamada dentro de aCATransaction
, porque o redesenho real pode (e provavelmente ocorrerá) algumas vezes mais tarde. A boa abordagem é usar propriedades personalizadas, conforme descrito nesta resposta .fonte
CALayer
impedir onoImplicitAnimations
trabalho. Talvez você deva marcar sua própria resposta como correta e explicar o que havia de errado com essa camada?CALayer
instância errada (eu tinha duas na época).NSNull
não implementa oCAAction
protocolo e este não é um protocolo que possui apenas métodos opcionais. Este código também falha e você não pode nem traduzir isso rapidamente. Melhor solução: faça seu objeto estar em conformidade com oCAAction
protocolo (com umrunActionForKey:object:arguments:
método vazio que não faz nada) e retorne emself
vez de[NSNull null]
. O mesmo efeito, mas seguro (não trava, com certeza) e também funciona no Swift.Aqui está uma solução mais eficiente, semelhante à resposta aceita, mas para Swift . Em alguns casos, será melhor do que criar uma transação toda vez que você modificar o valor, o que é uma preocupação de desempenho, como outros já mencionaram, por exemplo, casos de uso comuns de arrastar a posição da camada a 60fps.
Consulte os documentos da apple para saber como as ações da camada são resolvidas . A implementação do delegado pularia mais um nível na cascata, mas, no meu caso, isso era muito confuso devido à advertência de que o delegado precisava ser definido para o UIView associado .
Editar: atualizado graças ao comentarista apontando que
NSNull
está em conformidadeCAAction
.fonte
NullAction
para o Swift, jáNSNull
está em conformidade , paraCAAction
que você possa fazer o mesmo que você faz no objetivo C: layer.actions = ["position": NSNull ()]Com base na resposta de Sam e nas dificuldades de Simon ... adicione a referência de delegado depois de criar o CSShapeLayer:
... em outro lugar no arquivo "m" ...
Essencialmente o mesmo que o de Sam, sem a capacidade de alternar através do arranjo variável personalizado "disableImplicitAnimations". Mais uma abordagem "hard-wire".
fonte
Na verdade, não encontrei nenhuma das respostas certas. O método que resolve o problema para mim foi o seguinte:
Em seguida, você pode qualquer lógica nele, para desativar uma animação específica, mas como eu queria removê-las, retornei nulo.
fonte
Para desativar animações de camada implícitas no Swift
fonte
disableActions()
vez, pois parece que faz a mesma coisa, mas na verdade é para obter o valor atual. Eu acho que também está marcado@discardable
, dificultando a identificação. Fonte: developer.apple.com/documentation/quartzcore/catransaction/…Descobriu um método mais simples para desativar a ação dentro de um
CATransaction
que chama internamentesetValue:forKey:
akCATransactionDisableActions
chave:Rápido:
fonte
Adicione isso à sua classe personalizada na qual você está implementando o método -drawRect (). Faça alterações no código para atender às suas necessidades, para mim, a 'opacidade' fez o truque para interromper a animação de desbotamento.
fonte
Se você precisar de uma correção muito rápida (mas reconhecidamente hacky), pode valer a pena fazer (Swift):
fonte
view.layer?.actions = [:]
realmente não funciona. Definir a velocidade é feio, mas funciona.Atualizado para agilizar e desabilitar apenas uma animação de propriedade implícita no iOS, não no MacOS
Outro exemplo, neste caso, eliminando duas animações implícitas.
fonte
No iOS 7, existe um método de conveniência que faz exatamente isso:
fonte
Para desativar a animação irritante (embaçada) ao alterar a propriedade de seqüência de caracteres de um CATextLayer, você pode fazer isso:
e use-o assim (não esqueça de configurar seu CATextLayer corretamente, por exemplo, a fonte correta, etc.):
Você pode ver minha configuração completa do CATextLayer aqui:
Agora você pode atualizar o caTextLayer.string o quanto quiser =)
Inspirado por isso e por esta resposta.
fonte
Tente isso.
Aviso
Se você definir o delegado da instância do UITableView, às vezes ocorrerá uma falha (provavelmente o scrollview é o mais avançado chamado recursivamente).
fonte