Como adicionar uma borda na parte superior de um UIView
144
Minha pergunta está no título.
Eu não sei como adicionar uma borda em um lado específico, superior ou inferior, qualquer lado ...
layer.borderdesenha a borda para toda a exibição ...
Considero subclassificar UIViewe substituir um drawRectexagero aqui. Por que não adicionar uma extensão UIViewe adicionar subvisões de borda?
@discardableResult
func addBorders(edges:UIRectEdge,
color:UIColor,
inset:CGFloat=0.0,
thickness:CGFloat=1.0)->[UIView]{
var borders =[UIView]()@discardableResult
func addBorder(formats:String...)->UIView{
let border =UIView(frame:.zero)
border.backgroundColor = color
border.translatesAutoresizingMaskIntoConstraints =false
addSubview(border)
addConstraints(formats.flatMap {NSLayoutConstraint.constraints(withVisualFormat: $0,
options:[],
metrics:["inset": inset,"thickness": thickness],
views:["border": border])})
borders.append(border)return border
}if edges.contains(.top)|| edges.contains(.all){
addBorder(formats:"V:|-0-[border(==thickness)]","H:|-inset-[border]-inset-|")}if edges.contains(.bottom)|| edges.contains(.all){
addBorder(formats:"V:[border(==thickness)]-0-|","H:|-inset-[border]-inset-|")}if edges.contains(.left)|| edges.contains(.all){
addBorder(formats:"V:|-inset-[border]-inset-|","H:|-0-[border(==thickness)]")}if edges.contains(.right)|| edges.contains(.all){
addBorder(formats:"V:|-inset-[border]-inset-|","H:[border(==thickness)]-0-|")}return borders
}// Usage:
view.addBorder(edges:[.all])// All with default arguments
view.addBorder(edges:[.top], color:.green)// Just Top, green, default thickness
view.addBorder(edges:[.left,.right,.bottom], color:.red, thickness:3)// All except Top, red, thickness 3
Com esse código, você também não está vinculado à sua subclasse, pode aplicá-lo a tudo e qualquer coisa que herda UIView- reutilizável no seu projeto e em qualquer outro. Passe outros argumentos para seus métodos para definir outras cores e larguras. Muitas opções
A única desvantagem aqui é que ela não pode ser redimensionada.
31814 Peter PWeese
2
Pode usar um UIView e adicionar restrições de layout automático. Mesmo princípio.
Adam Waite
1
@PeterDeWeese Isso também não é uma desvantagem - se você deseja controlar o tamanho da borda, tudo o que você precisa fazer é algo como: - (void) addUpperBorderWithSize: (CGFloat) size E substitua a constante pelo parâmetro na função . O mesmo vale para outros parâmetros, como cores.
o.shnn
1
@ AdamWaite, essa variante de layout automático parece muito boa. Obrigado !
manonthemoon
2
Obrigado por compartilhar, eu faço uma versão do Objective-C com restrição de layout automático aqui .
Itachi
99
Adicionado recurso para cantos arredondados à postagem original de Adam Waite e às várias edições
Importante !: Não se esqueça de adicionar 'label.layoutIfNeeded ()' logo antes de chamar 'addborder' como comentado anteriormente
Nota: Eu testei isso apenas no UILabels.
extensão CALayer {
enumBorderSide{case top
case right
case bottom
case left
case notRight
case notLeft
case topAndBottom
case all
}enumCorner{case topLeft
case topRight
case bottomLeft
case bottomRight
}
func addBorder(side:BorderSide, thickness:CGFloat, color:CGColor, maskedCorners:CACornerMask?= nil){
var topWidth = frame.size.width; var bottomWidth = topWidth
var leftHeight = frame.size.height; var rightHeight = leftHeight
var topXOffset:CGFloat=0; var bottomXOffset:CGFloat=0
var leftYOffset:CGFloat=0; var rightYOffset:CGFloat=0// Draw the corners and set side offsetsswitch maskedCorners {case[.layerMinXMinYCorner,.layerMaxXMinYCorner]:// Top only
addCorner(.topLeft, thickness: thickness, color: color)
addCorner(.topRight, thickness: thickness, color: color)
topWidth -= cornerRadius*2
leftHeight -= cornerRadius; rightHeight -= cornerRadius
topXOffset = cornerRadius; leftYOffset = cornerRadius; rightYOffset = cornerRadius
case[.layerMinXMaxYCorner,.layerMaxXMaxYCorner]:// Bottom only
addCorner(.bottomLeft, thickness: thickness, color: color)
addCorner(.bottomRight, thickness: thickness, color: color)
bottomWidth -= cornerRadius*2
leftHeight -= cornerRadius; rightHeight -= cornerRadius
bottomXOffset = cornerRadius
case[.layerMinXMinYCorner,.layerMinXMaxYCorner]:// Left only
addCorner(.topLeft, thickness: thickness, color: color)
addCorner(.bottomLeft, thickness: thickness, color: color)
topWidth -= cornerRadius; bottomWidth -= cornerRadius
leftHeight -= cornerRadius*2
leftYOffset = cornerRadius; topXOffset = cornerRadius; bottomXOffset = cornerRadius;case[.layerMaxXMinYCorner,.layerMaxXMaxYCorner]:// Right only
addCorner(.topRight, thickness: thickness, color: color)
addCorner(.bottomRight, thickness: thickness, color: color)
topWidth -= cornerRadius; bottomWidth -= cornerRadius
rightHeight -= cornerRadius*2
rightYOffset = cornerRadius
case[.layerMaxXMinYCorner,.layerMaxXMaxYCorner,// All.layerMinXMaxYCorner,.layerMinXMinYCorner]:
addCorner(.topLeft, thickness: thickness, color: color)
addCorner(.topRight, thickness: thickness, color: color)
addCorner(.bottomLeft, thickness: thickness, color: color)
addCorner(.bottomRight, thickness: thickness, color: color)
topWidth -= cornerRadius*2; bottomWidth -= cornerRadius*2
topXOffset = cornerRadius; bottomXOffset = cornerRadius
leftHeight -= cornerRadius*2; rightHeight -= cornerRadius*2
leftYOffset = cornerRadius; rightYOffset = cornerRadius
default:break}// Draw the sidesswitch side {case.top:
addLine(x: topXOffset, y:0, width: topWidth, height: thickness, color: color)case.right:
addLine(x: frame.size.width - thickness, y: rightYOffset, width: thickness, height: rightHeight, color: color)case.bottom:
addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)case.left:
addLine(x:0, y: leftYOffset, width: thickness, height: leftHeight, color: color)// Multiple Sidescase.notRight:
addLine(x: topXOffset, y:0, width: topWidth, height: thickness, color: color)
addLine(x:0, y: leftYOffset, width: thickness, height: leftHeight, color: color)
addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)case.notLeft:
addLine(x: topXOffset, y:0, width: topWidth, height: thickness, color: color)
addLine(x: frame.size.width - thickness, y: rightYOffset, width: thickness, height: rightHeight, color: color)
addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)case.topAndBottom:
addLine(x: topXOffset, y:0, width: topWidth, height: thickness, color: color)
addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)case.all:
addLine(x: topXOffset, y:0, width: topWidth, height: thickness, color: color)
addLine(x: frame.size.width - thickness, y: rightYOffset, width: thickness, height: rightHeight, color: color)
addLine(x: bottomXOffset, y: frame.size.height - thickness, width: bottomWidth, height: thickness, color: color)
addLine(x:0, y: leftYOffset, width: thickness, height: leftHeight, color: color)}}private func addLine(x:CGFloat, y:CGFloat, width:CGFloat, height:CGFloat, color:CGColor){
let border =CALayer()
border.frame =CGRect(x: x, y: y, width: width, height: height)
border.backgroundColor = color
addSublayer(border)}private func addCorner(_ corner:Corner, thickness:CGFloat, color:CGColor){// Set default to top left
let width = frame.size.width; let height = frame.size.height
var x = cornerRadius
var startAngle:CGFloat=.pi; var endAngle:CGFloat=.pi*3/2switch corner {case.bottomLeft: startAngle =.pi/2; endAngle =.pi
case.bottomRight:
x = width - cornerRadius
startAngle =0; endAngle =.pi/2case.topRight:
x = width - cornerRadius
startAngle =.pi*3/2; endAngle =0default:break}
let cornerPath =UIBezierPath(arcCenter:CGPoint(x: x, y: height /2),
radius: cornerRadius - thickness,
startAngle: startAngle,
endAngle: endAngle,
clockwise:true)
let cornerShape =CAShapeLayer()
cornerShape.path = cornerPath.cgPath
cornerShape.lineWidth = thickness
cornerShape.strokeColor = color
cornerShape.fillColor = nil
addSublayer(cornerShape)}
Para fazê-lo funcionar, você precisa adicionar view.layoutIfNeeded()um pouco antes de ligar view.layer.addBorder(...). Em seguida, ele trabalha na Swift 3
Adam Studenic
está funcionando bem. adicione a linha neste métodooverride func viewDidLayoutSubviews()
Antony Raphel 12/06
60
A melhor maneira para mim é uma categoria no UIView, mas em adding viewsvez do CALayers, para que possamostake advantage of AutoresizingMasks garantir que as bordas sejam redimensionadas junto com a superview.
Essa é de longe uma das melhores soluções para esse problema. A maioria das outras soluções oferecidas NÃO respeita as alterações de exibição (e, portanto, a rotação do dispositivo ou as exibições divididas). Este faz.
Womble
1
como isso pode ser adaptado para suportar cantos arredondados?
Isso desenha uma linha vermelha de 2 pixels como uma borda superior. Todas as outras variações mencionadas são deixadas como um exercício trivial para o leitor.
É o único caminho para isso ??? Portanto, se eu precisar fazer uma exibição com uma borda superior e outra com borda inferior e outra exibição ... Quero dizer sempre uma exibição específica com uma borda ou duas, terei que criar uma subclasse para cada caso específico ??? Eu não sei se é muito bom para criar classe apenas para adicionar bordas ...
manonthemoon
1
Não. Pense nisso. Sua UIViewsubclasse pode ter uma propriedade que determina quais bordas são drawRect:desenhadas. Esta propriedade pode ser definida com NS_OPTIONSpara que ela defina uma máscara de bits como a UIViewAutoresizingmáscara de bits. Se, por qualquer motivo, você realmente se opuser a subclassificar UIView, basta adicionar uma subvisão pequena de 1 a 2 pixels de altura (ou ampla) e fornecer as dimensões que deseja simular uma borda.
Solução simples assim ... com uma UIView sobrecarga comparando a nu CALayer
Soberman
depois de ler todas as outras soluções, pensei em adicionar uma pequena visão também. Todo esse trabalho para uma fronteira! Esta solução requer apenas alguns pinos para funcionar também no layout automático. Muito mais fácil de entender.
Noobmcgoobs
Obrigado, adicionei uma observação acima para que os codificadores só sejam usados se o aplicativo não girar.
Travis M.
15
Pergunta antiga, mas a solução de pagamento automático com ajustes de borda de tempo de execução ainda está faltando.
borders(for:[.left,.bottom], width:2, color:.red)
A seguinte extensão UIView adicionará a borda apenas nas bordas fornecidas. Se você alterar as bordas no tempo de execução, as bordas serão ajustadas de acordo.
extension UIView{
func borders(for edges:[UIRectEdge], width:CGFloat=1, color:UIColor=.black){if edges.contains(.all){
layer.borderWidth = width
layer.borderColor = color.cgColor
}else{
let allSpecificBorders:[UIRectEdge]=[.top,.bottom,.left,.right]for edge in allSpecificBorders {if let v = viewWithTag(Int(edge.rawValue)){
v.removeFromSuperview()}if edges.contains(edge){
let v =UIView()
v.tag =Int(edge.rawValue)
v.backgroundColor = color
v.translatesAutoresizingMaskIntoConstraints =false
addSubview(v)
var horizontalVisualFormat ="H:"
var verticalVisualFormat ="V:"switch edge {caseUIRectEdge.bottom:
horizontalVisualFormat +="|-(0)-[v]-(0)-|"
verticalVisualFormat +="[v(\(width))]-(0)-|"caseUIRectEdge.top:
horizontalVisualFormat +="|-(0)-[v]-(0)-|"
verticalVisualFormat +="|-(0)-[v(\(width))]"caseUIRectEdge.left:
horizontalVisualFormat +="|-(0)-[v(\(width))]"
verticalVisualFormat +="|-(0)-[v]-(0)-|"caseUIRectEdge.right:
horizontalVisualFormat +="[v(\(width))]-(0)-|"
verticalVisualFormat +="|-(0)-[v]-(0)-|"default:break}
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: horizontalVisualFormat, options:.directionLeadingToTrailing, metrics: nil, views:["v": v]))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: verticalVisualFormat, options:.directionLeadingToTrailing, metrics: nil, views:["v": v]))}}}}}
Peguei as respostas de Adam Waite e Pauls e as combinei. Também adicionei a possibilidade de unir as arestas selecionadas, portanto, você precisa chamar apenas uma função como esta:
Passei pelas soluções oferecidas. Muitos são baseados em quadros Essa é uma extensão simples que funciona com AutoLayout - use View em vez de Layer para garantir que possamos usar AutoLayout - Single subview com 4 restrições
Construindo fora de de NSBum resposta, tomei uma abordagem semelhante e criou esta subclasse UIView simples para que ele funcione no Interface Builder e trabalha com restrições: ligação github
Usando CGContextFillRect em vez de CGContextStrokePath, eu era capaz de manter previsivelmente as linhas completamente sólidas e dentro os limites da vista.
- Basicamente, basta inserir um UIView no Interface Builder e alterar seu tipo de classe para NAUIViewWithBorders.
- Então, no viewDidLoad do seu VC, faça algo como:
/* For a top border only ———————————————- */
self.myBorderView.borderColorTop =[UIColor redColor];
self.myBorderView..borderWidthsAll =1.0f;/* For borders with different colors and widths ————————— */
self.myBorderView.borderWidths =UIEdgeInsetsMake(2.0,4.0,6.0,8.0);
self.myBorderView.borderColorTop =[UIColor blueColor];
self.myBorderView.borderColorRight =[UIColor redColor];
self.myBorderView.borderColorBottom =[UIColor greenColor];
self.myBorderView.borderColorLeft =[UIColor darkGrayColor];
Aqui está um link direto para o arquivo .m para que você possa ver a implementação. Há um projeto de demonstração também. Espero que isso ajude alguém :)
Minha resposta para uma pergunta semelhante: https://stackoverflow.com/a/27141956/435766
Pessoalmente, prefiro seguir o caminho da categoria nesse caso, pois quero poder usá-lo em qualquer subclasse do UIView.
Aqui está uma solução simples. Adicione uma etiqueta à sua UIView, limpe o texto na etiqueta e defina a cor de fundo da etiqueta como a sua borda. Defina a origem (x,y)do seu rótulo como a origem (x,y)da sua exibição. e defina a largura do rótulo como a sua UIView, defina a altura como 1 ou 2 (para a altura da borda na parte superior da sua UIView). E isso deve fazer o truque.
Nenhum ponto em ter um rótulo, em seguida, pode muito bem ser outro UIView
maor10
1
Isso realmente não responde à questão de adicionar apenas a borda superior a uma visão geral. Esta é uma solução rápida que provavelmente não funcionaria para problemas mais complexos.
Será chamado de 'addSublayer' sempre que o layout for atualizado?
byJeevan
1
Basta postar aqui para ajudar alguém que deseja adicionar bordas. Fiz algumas alterações na resposta aceita aqui, etiqueta rápida apenas com a borda esquerda . Largura alterada no caso UIRectEdge.Topde CGRectGetHeight(self.frame)para CGRectGetWidth(self.frame)e no caso UIRectEdge.Bottomde UIScreen.mainScreen().bounds.widthparaCGRectGetWidth(self.frame) obter fronteiras corretamente. Usando o Swift 2.
Inspirado por @Addison, reescrevi a extensão sem o uso de qualquer estrutura de terceiros, pois ele usou o SnapKit e o CocoaLumberjack.
Como na abordagem @Addisons, também estou removendo bordas adicionadas anteriormente, portanto essa implementação deve ser agradável com visualizações reutilizáveis como células de tabela e células de coleção.
fileprivate classBorderView:UIView{}// dummy class to help us differentiate among border views and other views// to enabling us to remove existing borders and place new ones
extension UIView{
func setBorders(toEdges edges:[UIRectEdge], withColor color:UIColor, inset:CGFloat=0, thickness:CGFloat){// Remove existing edgesfor view in subviews {if view is BorderView{
view.removeFromSuperview()}}// Add new edgesif edges.contains(.all){
addSidedBorder(toEdge:[.left,.right,.top,.bottom], withColor: color, inset: inset, thickness: thickness)}if edges.contains(.left){
addSidedBorder(toEdge:[.left], withColor: color, inset: inset, thickness: thickness)}if edges.contains(.right){
addSidedBorder(toEdge:[.right], withColor: color, inset: inset, thickness: thickness)}if edges.contains(.top){
addSidedBorder(toEdge:[.top], withColor: color, inset: inset, thickness: thickness)}if edges.contains(.bottom){
addSidedBorder(toEdge:[.bottom], withColor: color, inset: inset, thickness: thickness)}}private func addSidedBorder(toEdge edges:[RectangularEdges], withColor color:UIColor, inset:CGFloat=0, thickness:CGFloat){for edge in edges {
let border =BorderView(frame:.zero)
border.backgroundColor = color
addSubview(border)
border.translatesAutoresizingMaskIntoConstraints =falseswitch edge {case.left:NSLayoutConstraint.activate([
border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: inset),
border.topAnchor.constraint(equalTo: self.topAnchor, constant: inset),
border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant:-inset),NSLayoutConstraint(item: border, attribute:.width, relatedBy:.equal, toItem: nil, attribute:.width, multiplier:1, constant: thickness)])case.right:NSLayoutConstraint.activate([
border.rightAnchor.constraint(equalTo: self.rightAnchor, constant:-inset),
border.topAnchor.constraint(equalTo: self.topAnchor, constant: inset),
border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant:-inset),NSLayoutConstraint(item: border, attribute:.width, relatedBy:.equal, toItem: nil, attribute:.width, multiplier:1, constant: thickness)])case.top:NSLayoutConstraint.activate([
border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: inset),
border.rightAnchor.constraint(equalTo: self.rightAnchor, constant:-inset),
border.topAnchor.constraint(equalTo: self.topAnchor, constant: inset),NSLayoutConstraint(item: border, attribute:.height, relatedBy:.equal, toItem: nil, attribute:.height, multiplier:1, constant: thickness)])case.bottom:NSLayoutConstraint.activate([
border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: inset),
border.rightAnchor.constraint(equalTo: self.rightAnchor, constant:-inset),
border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant:-inset),NSLayoutConstraint(item: border, attribute:.height, relatedBy:.equal, toItem: nil, attribute:.height, multiplier:1, constant: thickness)])}}}privateenumRectangularEdges{case left
case right
case top
case bottom
}}
Se eu estiver construindo a partir do storyboard, prefiro adicionar um UIViewpor trás do meu útil UIView... Se eu quiser criar uma borda na parte superior da minha UIView, apenas aumento a altura do plano UIViewde fundo pela largura da minha borda. O mesmo pode ser feito para qualquer outro lado :)
Pessoalmente, gosto da subclassificação do view + drawRect, mas aqui está apenas outra maneira de fazer isso (e funciona da mesma forma que a resposta aceita por @ If Pollavith):
Sua nova camada de borda pode ser configurada para ter as dimensões desejadas. Então, como a resposta de @Se Pollavith, você cria uma camada para ser tão alta quanto quiser e tão larga quanto a vista que deseja delimitar. Use a definição de quadro da camada para colocá-lo onde quiser e, em seguida, adicione-o como uma subcamada à sua exibição.
Para referência, meu próprio requisito era colocar uma borda no lado esquerdo da vista (não recorte e cole esse código e me diga apenas porque não coloca uma borda no topo da vista - modificar o código abaixo é bastante simples):
Além do n8tr, pode-se acrescentar que existe uma disponibilidade para configurá-los no storyboard:
- adicione duas propriedades como borderColore borderWidthno arquivo .h;
- então você pode adicionar keyPathsno storyboard, veja o link para a captura de tela
Nota: a maioria das soluções aqui não é adaptável e não será redimensionada. As soluções que serão redimensionadas terão uma enorme impacto no tempo de inicialização, uma vez que usam muita CPU.
Você pode usar esta solução abaixo. Ele funciona em UIBezierPaths, que são mais leves que as camadas, causando tempos de inicialização rápidos. É fácil de usar, veja as instruções abaixo.
Respostas:
Considero subclassificar
UIView
e substituir umdrawRect
exagero aqui. Por que não adicionar uma extensãoUIView
e adicionar subvisões de borda?Com esse código, você também não está vinculado à sua subclasse, pode aplicá-lo a tudo e qualquer coisa que herda
UIView
- reutilizável no seu projeto e em qualquer outro. Passe outros argumentos para seus métodos para definir outras cores e larguras. Muitas opçõesfonte
Adicionado recurso para cantos arredondados à postagem original de Adam Waite e às várias edições
Importante !: Não se esqueça de adicionar 'label.layoutIfNeeded ()' logo antes de chamar 'addborder' como comentado anteriormente
Nota: Eu testei isso apenas no UILabels.
extensão CALayer {
}
fonte
view.layoutIfNeeded()
um pouco antes de ligarview.layer.addBorder(...)
. Em seguida, ele trabalha na Swift 3override func viewDidLayoutSubviews()
A melhor maneira para mim é uma categoria no UIView, mas em
adding views
vez do CALayers, para que possamostake advantage of AutoresizingMasks
garantir que as bordas sejam redimensionadas junto com a superview.Objetivo C
Swift 5
fonte
Swift 3.0
Swift 4.1
fonte
Subclasse
UIView
e implementedrawRect:
em sua subclasse, por exemplo:Objetivo-c
Swift 4
Isso desenha uma linha vermelha de 2 pixels como uma borda superior. Todas as outras variações mencionadas são deixadas como um exercício trivial para o leitor.
Recomenda-se o Guia de Programação em Quartzo 2D .
fonte
UIView
subclasse pode ter uma propriedade que determina quais bordas sãodrawRect:
desenhadas. Esta propriedade pode ser definida comNS_OPTIONS
para que ela defina uma máscara de bits como aUIViewAutoresizing
máscara de bits. Se, por qualquer motivo, você realmente se opuser a subclassificarUIView
, basta adicionar uma subvisão pequena de 1 a 2 pixels de altura (ou ampla) e fornecer as dimensões que deseja simular uma borda.Código da resposta selecionada, caso alguém queira.
NOTA: Isso não funciona com o layout automático (também conhecido como dispositivo rotativo para paisagem etc.).
Primeiro defina uma espessura:
Em seguida, basta copiar, use qualquer um ou todos esses para definir a borda que você deseja definir.
Borda superior
Borda inferior
Borda esquerda
Borda direita
fonte
Pergunta antiga, mas a solução de pagamento automático com ajustes de borda de tempo de execução ainda está faltando.
A seguinte extensão UIView adicionará a borda apenas nas bordas fornecidas. Se você alterar as bordas no tempo de execução, as bordas serão ajustadas de acordo.
fonte
Versão rápida:
Editar: Para versões atualizadas, verifique meu repositório aqui: https://github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/UIViewExtensions.swift
Veja as partes addBorder
fonte
Peguei as respostas de Adam Waite e Pauls e as combinei. Também adicionei a possibilidade de unir as arestas selecionadas, portanto, você precisa chamar apenas uma função como esta:
ou então:
O que você precisa implementar é uma categoria no UIView, conforme sugerido em outras respostas com a seguinte implementação:
fonte
// MARK: - Adicionar borda esquerda para exibição
// MARK: - Adicionar borda direita para exibição
// MARK: - Adicionar borda inferior para exibição
fonte
Swift 4.2 e AutoLayout
Passei pelas soluções oferecidas. Muitos são baseados em quadros Essa é uma extensão simples que funciona com AutoLayout - use View em vez de Layer para garantir que possamos usar AutoLayout - Single subview com 4 restrições
Use da seguinte maneira:
fonte
Fiz algumas alterações na resposta de Dan para poder adicionar bordas a várias bordas com um comando:
Aqui está o código completo:
fonte
Construindo fora de de NSBum resposta, tomei uma abordagem semelhante e criou esta subclasse UIView simples para que ele funcione no Interface Builder e trabalha com restrições: ligação github
Usando CGContextFillRect em vez de CGContextStrokePath, eu era capaz de manter previsivelmente as linhas completamente sólidas e dentro os limites da vista.
Aqui está o meu post sobre isso: http://natrosoft.com/?p=55
- Basicamente, basta inserir um UIView no Interface Builder e alterar seu tipo de classe para NAUIViewWithBorders.
- Então, no viewDidLoad do seu VC, faça algo como:
Aqui está um link direto para o arquivo .m para que você possa ver a implementação. Há um projeto de demonstração também. Espero que isso ajude alguém :)
fonte
Minha resposta para uma pergunta semelhante: https://stackoverflow.com/a/27141956/435766 Pessoalmente, prefiro seguir o caminho da categoria nesse caso, pois quero poder usá-lo em qualquer subclasse do UIView.
fonte
fonte
Aqui está uma solução simples. Adicione uma etiqueta à sua
UIView
, limpe o texto na etiqueta e defina a cor de fundo da etiqueta como a sua borda. Defina a origem(x,y)
do seu rótulo como a origem(x,y)
da sua exibição. e defina a largura do rótulo como a suaUIView
, defina a altura como 1 ou 2 (para a altura da borda na parte superior da suaUIView
). E isso deve fazer o truque.fonte
Versão Swift 3
Para definir a borda correspondente, você deve substituir o método viewDidLayoutSubviews () :
fonte
Basta postar aqui para ajudar alguém que deseja adicionar bordas. Fiz algumas alterações na resposta aceita aqui, etiqueta rápida apenas com a borda esquerda . Largura alterada no caso
UIRectEdge.Top
deCGRectGetHeight(self.frame)
paraCGRectGetWidth(self.frame)
e no casoUIRectEdge.Bottom
deUIScreen.mainScreen().bounds.width
paraCGRectGetWidth(self.frame)
obter fronteiras corretamente. Usando o Swift 2.Finalmente, a extensão é:
fonte
Caso alguém precise da versão do Xamarin:
fonte
Aqui está uma versão Swift 4 da resposta de Pauls
fonte
Inspirado por @Addison, reescrevi a extensão sem o uso de qualquer estrutura de terceiros, pois ele usou o SnapKit e o CocoaLumberjack.
Como na abordagem @Addisons, também estou removendo bordas adicionadas anteriormente, portanto essa implementação deve ser agradável com visualizações reutilizáveis como células de tabela e células de coleção.
fonte
Se eu estiver construindo a partir do storyboard, prefiro adicionar um
UIView
por trás do meu útilUIView
... Se eu quiser criar uma borda na parte superior da minhaUIView
, apenas aumento a altura do planoUIView
de fundo pela largura da minha borda. O mesmo pode ser feito para qualquer outro lado :)fonte
Pessoalmente, gosto da subclassificação do view + drawRect, mas aqui está apenas outra maneira de fazer isso (e funciona da mesma forma que a resposta aceita por @ If Pollavith):
Sua nova camada de borda pode ser configurada para ter as dimensões desejadas. Então, como a resposta de @Se Pollavith, você cria uma camada para ser tão alta quanto quiser e tão larga quanto a vista que deseja delimitar. Use a definição de quadro da camada para colocá-lo onde quiser e, em seguida, adicione-o como uma subcamada à sua exibição.
Para referência, meu próprio requisito era colocar uma borda no lado esquerdo da vista (não recorte e cole esse código e me diga apenas porque não coloca uma borda no topo da vista - modificar o código abaixo é bastante simples):
Eu acho que o único benefício moderado sobre isso e criar um pequeno UIView ou UILabel é que o CALayer é supostamente 'mais leve', e há muitas visões interessantes (como nas opiniões) sobre ultrapassar o drawRect versus usar o CALayers (como aqui : iOS: Usando o 'drawRect:' do UIView vs. o delagado de sua camada 'drawLayer: inContext:' ).
Animal451
Eu gosto da cor azul.
fonte
Além do n8tr, pode-se acrescentar que existe uma disponibilidade para configurá-los no storyboard:
- adicione duas propriedades como
borderColor
eborderWidth
no arquivo .h;- então você pode adicionar
keyPaths
no storyboard, veja o link para a captura de telafonte
Conversão DanShev para Swift 3
fonte
Para o Xamarin em C #, apenas crio a borda embutida ao adicionar a subcamada
Você pode organizar isso (como sugerido por outras pessoas) para as margens inferior, esquerda e direita.
fonte
Você também pode verificar esta coleção das categorias UIKit e Foundation: https://github.com/leszek-s/LSCategories
Permite adicionar borda em um lado do UIView com uma única linha de código:
e ele lida adequadamente com a rotação de visualizações, enquanto a maioria das respostas postadas aqui não é adequada.
fonte
Nota: a maioria das soluções aqui não é adaptável e não será redimensionada. As soluções que serão redimensionadas terão uma enorme impacto no tempo de inicialização, uma vez que usam muita CPU.
Você pode usar esta solução abaixo. Ele funciona em UIBezierPaths, que são mais leves que as camadas, causando tempos de inicialização rápidos. É fácil de usar, veja as instruções abaixo.
fonte
Para definir a borda superior e a borda inferior para uma UIView no Swift.
fonte
Nos Swift 4 e 3
fonte