Fiz um CALayer
com um adicionado CATextLayer
e o texto sai borrado. Nos documentos, eles falam sobre "suavização de subpixel", mas isso não significa muito para mim. Alguém tem um trecho de código que faz um CATextLayer
com um trecho de texto claro?
Aqui está o texto da documentação da Apple:
Nota: CATextLayer desativa suavização de subpixel ao renderizar texto. O texto só pode ser desenhado usando suavização de subpixel quando é composto em um fundo opaco existente ao mesmo tempo em que é rasterizado. Não há como desenhar o texto suavizado de subpixel por si só, seja em uma imagem ou uma camada, separadamente antes de ter os pixels de fundo para tecer os pixels de texto. Definir a propriedade opacidade da camada como SIM não altera o modo de renderização.
A segunda frase implica que é possível obter um texto com boa aparência se convertê- composites
lo em um existing opaque background at the same time that it's rasterized.
Isso é ótimo, mas como faço para compô-lo e como dar a ele um fundo opaco e como rasterizá-lo?
O código que eles usam em seu exemplo de menu de quiosque é o seguinte: (É OS X, não iOS, mas presumo que funcione!)
NSInteger i;
for (i=0;i<[names count];i++) {
CATextLayer *menuItemLayer=[CATextLayer layer];
menuItemLayer.string=[self.names objectAtIndex:i];
menuItemLayer.font=@"Lucida-Grande";
menuItemLayer.fontSize=fontSize;
menuItemLayer.foregroundColor=whiteColor;
[menuItemLayer addConstraint:[CAConstraint
constraintWithAttribute:kCAConstraintMaxY
relativeTo:@"superlayer"
attribute:kCAConstraintMaxY
offset:-(i*height+spacing+initialOffset)]];
[menuItemLayer addConstraint:[CAConstraint
constraintWithAttribute:kCAConstraintMidX
relativeTo:@"superlayer"
attribute:kCAConstraintMidX]];
[self.menuLayer addSublayer:menuItemLayer];
} // end of for loop
Obrigado!
EDIT: Adicionando o código que eu realmente usei que resultou em texto borrado. É de uma questão relacionada que postei sobre adicionar um em UILabel
vez de um, CATextLayer
mas obter uma caixa preta. http://stackoverflow.com/questions/3818676/adding-a-uilabels-layer-to-a-calayer-and-it-just-shows-black-box
CATextLayer* upperOperator = [[CATextLayer alloc] init];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGFloat components1[4] = {1.0, 1.0, 1.0, 1.0};
CGColorRef almostWhite = CGColorCreate(space,components1);
CGFloat components2[4] = {0.0, 0.0, 0.0, 1.0};
CGColorRef almostBlack = CGColorCreate(space,components2);
CGColorSpaceRelease(space);
upperOperator.string = [NSString stringWithFormat:@"13"];
upperOperator.bounds = CGRectMake(0, 0, 100, 50);
upperOperator.foregroundColor = almostBlack;
upperOperator.backgroundColor = almostWhite;
upperOperator.position = CGPointMake(50.0, 25.0);
upperOperator.font = @"Helvetica-Bold";
upperOperator.fontSize = 48.0f;
upperOperator.borderColor = [UIColor redColor].CGColor;
upperOperator.borderWidth = 1;
upperOperator.alignmentMode = kCAAlignmentCenter;
[card addSublayer:upperOperator];
[upperOperator release];
CGColorRelease(almostWhite);
CGColorRelease(almostBlack);
EDIT 2: Veja minha resposta abaixo para saber como isso foi resolvido. sbg.
fonte
Respostas:
Resposta curta - você precisa definir a escala de conteúdo:
Há algum tempo, aprendi que, quando você tem um código de desenho personalizado, precisa verificar a tela retina e dimensionar seus gráficos de acordo.
UIKit
cuida da maior parte disso, incluindo o dimensionamento da fonte.Não é assim com
CATextLayer.
Meu borrão veio de ter um
.zPosition
que não era zero, ou seja, eu tinha uma transformação aplicada à minha camada pai. Ao definir isso para zero, o borrão foi embora e foi substituído por pixelização grave.Depois de pesquisar alto e baixo, descobri que você pode definir
.contentsScale
umCATextLayer
e para[[UIScreen mainScreen] scale]
que corresponda à resolução da tela. (Presumo que isso funcione para não retina, mas não verifiquei - muito cansado)Depois de incluir isso no meu,
CATextLayer
o texto ficou nítido. Observação - não é necessário para a camada pai.E o borrão? Ele volta quando você está girando em 3D, mas você não percebe porque o texto começa claro e, enquanto está em movimento, não dá para perceber.
Problema resolvido!
fonte
textLayer.contentScale = [[UIScreen mainScreen] scale];
BTW, eu também gosto de respostas longas :)_textLayer.contentsScale = [[UIScreen mainScreen] scale];
Está faltando um "s";)Rápido
Defina a camada de texto para usar a mesma escala da tela.
Antes:
Depois de:
fonte
Em primeiro lugar, gostaria de salientar que você marcou sua pergunta com iOS, mas os gerenciadores de restrições estão disponíveis apenas no OSX, então não tenho certeza de como você está fazendo isso funcionar, a menos que tenha conseguido um link para ele no simulador de alguma forma. No dispositivo, essa funcionalidade não está disponível.
A seguir, vou apenas apontar que eu crio CATextLayers com frequência e nunca tenho o problema de desfoque a que você está se referindo, então sei que isso pode ser feito. Resumindo, esse desfoque ocorre porque você não está posicionando sua camada no pixel inteiro. Lembre-se de que ao definir a posição de uma camada, você usa valores flutuantes para x e y. Se esses valores tiverem números após o decimal, a camada não será posicionada em todo o pixel e, portanto, dará esse efeito de desfoque - cujo grau depende dos valores reais. Para testar isso, basta criar um CATextLayer e adicioná-lo explicitamente à árvore de camadas garantindo que seu parâmetro de posição esteja em um pixel inteiro. Por exemplo:
Se o seu texto ainda estiver borrado, há algo errado. O texto desfocado em sua camada de texto é um artefato de código escrito incorretamente e não um recurso pretendido da camada. Ao adicionar suas camadas a uma camada pai, você pode apenas forçar os valores xey para o pixel inteiro mais próximo e isso deve resolver seu problema de desfoque.
fonte
Antes de definir o shouldRasterize, você deve:
Se você não fizer o nº 1, a versão retina das subcamadas parecerá borrada, mesmo para CALayers normais.
fonte
Você deve fazer 2 coisas, a primeira foi mencionada acima:
Estenda CATextLayer e defina as propriedades opaque e contentsScale para suportar adequadamente a exibição de retina e, em seguida, renderize com suavização de serrilhado ativada para texto.
fonte
Se você veio procurando aqui por um problema semelhante para um CATextLayer no OSX, depois de muito bater cabeça na parede, obtive o texto claro nítido fazendo:
(Eu também defino o conteúdo da camada de plano de fundo das visualizações como o mesmo)
fonte
Isso é mais rápido e fácil: você só precisa definir a escala de conteúdo
fonte