Eu usei a resposta em Como criar um UILabel de canto arredondado no iPhone? e o código de Como é feita uma visualização retangular arredondada com transparência no iphone? para fazer esse código.
Então percebi que havia respondido à pergunta errada (dei um UILabel arredondado em vez de UIImage), então usei esse código para alterá-lo:
http://discussions.apple.com/thread.jspa?threadID=1683876
Faça um projeto do iPhone com o modelo View. No controlador de exibição, adicione isto:
- (void)viewDidLoad
{
CGRect rect = CGRectMake(10, 10, 200, 100);
MyView *myView = [[MyView alloc] initWithFrame:rect];
[self.view addSubview:myView];
[super viewDidLoad];
}
MyView
é apenas uma UIImageView
subclasse:
@interface MyView : UIImageView
{
}
Eu nunca tinha usado contextos gráficos antes, mas consegui manobrar esse código. Está faltando o código para dois dos cantos. Se você ler o código, poderá ver como eu implementei isso (excluindo algumas das CGContextAddArc
chamadas e excluindo alguns dos valores de raio no código. O código para todos os cantos está lá, use-o como ponto de partida e exclua o peças que criam cantos de que você não precisa.Tenha em mente que também pode fazer retângulos com 2 ou 3 cantos arredondados.
O código não é perfeito, mas tenho certeza que você pode arrumar um pouco.
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, int roundedCornerPosition)
{
// all corners rounded
// CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
// CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
// radius, M_PI / 4, M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius,
// radius, 0.0f, -M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
// -M_PI / 2, M_PI, 1);
// top left
if (roundedCornerPosition == 1) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
radius, M_PI / 4, M_PI / 2, 1);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);
}
// bottom left
if (roundedCornerPosition == 2) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
-M_PI / 2, M_PI, 1);
}
// add the other corners here
CGContextClosePath(context);
CGContextRestoreGState(context);
}
-(UIImage *)setImage
{
UIImage *img = [UIImage imageNamed:@"my_image.png"];
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, w, h);
addRoundedRectToPath(context, rect, 50, 1);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, rect, img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
return [UIImage imageWithCGImage:imageMasked];
}
texto alternativo http://nevan.net/skitch/skitched-20100224-092237.png
Não esqueça que você precisará obter a estrutura do QuartzCore para que isso funcione.
A partir do iOS 3.2, é possível usar a funcionalidade
UIBezierPath
s para criar um retângulo arredondado pronto para uso (onde apenas os cantos especificados são arredondados). Você pode usar isso como o caminho de aCAShapeLayer
e usá-lo como uma máscara para a camada da sua exibição:E é isso: não é necessário definir formas manualmente no Core Graphics, nem criar imagens mascaradas no Photoshop. A camada nem precisa ser invalidada. Aplicar o canto arredondado ou alterar para um novo canto é tão simples quanto definir um novo
UIBezierPath
e usá-loCGPath
como o caminho da camada de máscara. Ocorners
parâmetro dobezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
método é uma máscara de bits e, portanto, vários cantos podem ser arredondados ORing juntos.EDIT: Adicionando uma sombra
Se você deseja adicionar uma sombra a isso, é necessário um pouco mais de trabalho.
Como "
imageView.layer.mask = maskLayer
" aplica uma máscara, uma sombra normalmente não aparece fora dela. O truque é usar uma vista transparente e, em seguida, adicionar duas subcamadasCALayer
à camada da vista:shadowLayer
eroundedLayer
. Ambos precisam fazer uso doUIBezierPath
. A imagem é adicionada como o conteúdo deroundedLayer
.fonte
Eu usei esse código em muitos lugares no meu código e funciona 100% corretamente. Você pode alterar qualquer corder alterando uma propriedade "byRoundingCorners: UIRectCornerBottomLeft"
fonte
UITableView
-subviews (por exemplo,UITableViewCell
s ouUITableViewHeaderFooterView
s), isso resulta em uma suavidade ruim ao rolar . Outra abordagem para esse uso é essa solução com melhor desempenho (ela adiciona um cornerRadius a todos os cantos). Para 'mostrar' apenas cantos arredondados específicos (como os cantos superior e inferior direito), adicionei uma subvisão com um valor negativoframe.origin.x
e atribuai o cornerRadius à sua camada. Se alguém encontrou uma solução melhor, estou interessado.No iOS 11, agora podemos arredondar apenas alguns cantos
fonte
Extensão CALayer com sintaxe Swift 3+
Pode ser usado como:
fonte
O exemplo de stuarts para arredondar cantos específicos funciona muito bem. Se você deseja arredondar vários cantos, como o canto superior esquerdo e o direito, é assim que se faz
fonte
UITableView
-subviews (por exemplo,UITableViewCell
s ouUITableViewHeaderFooterView
s), isso resulta em uma suavidade ruim ao rolar . Outra abordagem para esse uso é essa solução com melhor desempenho (ela adiciona um cornerRadius a todos os cantos). Para 'mostrar' apenas cantos arredondados específicos (como os cantos superior e inferior direito), adicionei uma subvisão com um valor negativoframe.origin.x
e atribuai o cornerRadius à sua camada. Se alguém encontrou uma solução melhor, estou interessado.Obrigado por compartilhar. Aqui, gostaria de compartilhar a solução no swift 2.0 para obter mais referências sobre esse problema. (para conformar o protocolo do UIRectCorner)
fonte
existe uma resposta mais fácil e rápida que pode funcionar dependendo de suas necessidades e também funciona com sombras. você pode definir maskToBounds na superlayer como true e deslocar as camadas filho para que 2 dos seus cantos fiquem fora dos limites da superlayer, cortando efetivamente os cantos arredondados em 2 lados.
é claro que isso só funciona quando você deseja ter apenas 2 cantos arredondados no mesmo lado e o conteúdo da camada fica igual quando você corta alguns pixels de um lado. funciona muito bem com gráficos de barras arredondados apenas no lado superior.
fonte
Veja esta pergunta relacionada . Você terá que desenhar seu próprio retângulo em um
CGPath
com alguns cantos arredondados, adicionar oCGPath
ao seuCGContext
e depois prendê-lo usandoCGContextClip
.Você também pode desenhar o retângulo arredondado com valores alfa em uma imagem e usá-la para criar uma nova camada que você define como
mask
propriedade da sua camada ( consulte a documentação da Apple ).fonte
Meia década atrasada, mas acho que a maneira atual como as pessoas fazem isso não é 100% correta. Muitas pessoas tiveram o problema de que o uso do método UIBezierPath + CAShapeLayer interfere no layout automático, especialmente quando ele é definido no Storyboard. Não há respostas sobre isso, então decidi adicionar as minhas.
Existe uma maneira muito fácil de contornar isso: Desenhe os cantos arredondados na
drawRect(rect: CGRect)
função.Por exemplo, se eu quisesse os cantos arredondados no topo de uma UIView, subclasseia o UIView e usaria essa subclasse sempre que apropriado.
Essa é a melhor maneira de conquistar o problema e não leva tempo para se adaptar.
fonte
drawRect(_:)
se estiver fazendo um desenho personalizado em sua visualização (por exemplo, com gráficos principais), caso contrário, mesmo uma implementação vazia poderá afetar o desempenho. Criar uma nova camada de máscara sempre é desnecessário. Tudo o que você realmente precisa fazer é atualizar apath
propriedade da camada de máscara quando os limites da exibição mudarem e o local para fazer isso estiver dentro de uma substituição dolayoutSubviews()
método.Arredondar apenas alguns cantos não funcionará bem com redimensionamento automático ou layout automático.
Portanto, outra opção é usar regular
cornerRadius
e ocultar os cantos que você não deseja em outra visualização ou fora dos limites da superview, certificando-se de que ela esteja configurada para cortar seu conteúdo.fonte
Para adicionar à resposta e à adição , criei um simples, reutilizável
UIView
no Swift. Dependendo do seu caso de uso, convém fazer modificações (evite criar objetos em todos os layouts etc.), mas eu queria mantê-lo o mais simples possível. A extensão permite aplicar isso a outras visualizações (ex.UIImageView
) Com mais facilidade se você não gosta de subclassificar.Veja como você o aplicaria a
UIViewController
:fonte
Para finalizar a resposta de Stuart, você pode usar o método de canto arredondado da seguinte maneira:
Para aplicar o canto arredondado, basta:
fonte
Eu sugiro definir a máscara de uma camada. A própria máscara deve ser um
CAShapeLayer
objeto com um caminho dedicado. Você pode usar a próxima extensão UIView (Swift 4.2):fonte