que framework ios objective-c iphone uiview

ios - framework - Borde de línea discontinua alrededor de UIView



uikit ios (17)

¿Cómo agrego un borde de línea discontinua alrededor de UIView ?

Algo como esto


En Swift 3

let border = CAShapeLayer(); border.strokeColor = UIColor.black.cgColor; border.fillColor = nil; border.lineDashPattern = [4, 4]; border.path = UIBezierPath(rect: theView.bounds).cgPath border.frame = theView.bounds; theView.layer.addSublayer(border);


En swift 4 creé una extensión UIView con la siguiente función:

func borderDash(withRadius cornerRadius: Float, borderWidth: Float, borderColor: UIColor, dashSize: Int) { let currentFrame = self.bounds let shapeLayer = CAShapeLayer() let path = CGMutablePath() let radius = CGFloat(cornerRadius) // Points - Eight points that define the round border. Each border is defined by two points. let topLeftPoint = CGPoint(x: radius, y: 0) let topRightPoint = CGPoint(x: currentFrame.size.width - radius, y: 0) let middleRightTopPoint = CGPoint(x: currentFrame.size.width, y: radius) let middleRightBottomPoint = CGPoint(x: currentFrame.size.width, y: currentFrame.size.height - radius) let bottomRightPoint = CGPoint(x: currentFrame.size.width - radius, y: currentFrame.size.height) let bottomLeftPoint = CGPoint(x: radius, y: currentFrame.size.height) let middleLeftBottomPoint = CGPoint(x: 0, y: currentFrame.size.height - radius) let middleLeftTopPoint = CGPoint(x: 0, y: radius) // Points - Four points that are the center of the corners borders. let cornerTopRightCenter = CGPoint(x: currentFrame.size.width - radius, y: radius) let cornerBottomRightCenter = CGPoint(x: currentFrame.size.width - radius, y: currentFrame.size.height - radius) let cornerBottomLeftCenter = CGPoint(x: radius, y: currentFrame.size.height - radius) let cornerTopLeftCenter = CGPoint(x: radius, y: radius) // Angles - The corner radius angles. let topRightStartAngle = CGFloat(Double.pi * 3 / 2) let topRightEndAngle = CGFloat(0) let bottomRightStartAngle = CGFloat(0) let bottmRightEndAngle = CGFloat(Double.pi / 2) let bottomLeftStartAngle = CGFloat(Double.pi / 2) let bottomLeftEndAngle = CGFloat(Double.pi) let topLeftStartAngle = CGFloat(Double.pi) let topLeftEndAngle = CGFloat(Double.pi * 3 / 2) // Drawing a border around a view. path.move(to: topLeftPoint) path.addLine(to: topRightPoint) path.addArc(center: cornerTopRightCenter, radius: radius, startAngle: topRightStartAngle, endAngle: topRightEndAngle, clockwise: false) path.addLine(to: middleRightBottomPoint) path.addArc(center: cornerBottomRightCenter, radius: radius, startAngle: bottomRightStartAngle, endAngle: bottmRightEndAngle, clockwise: false) path.addLine(to: bottomLeftPoint) path.addArc(center: cornerBottomLeftCenter, radius: radius, startAngle: bottomLeftStartAngle, endAngle: bottomLeftEndAngle, clockwise: false) path.addLine(to: middleLeftTopPoint) path.addArc(center: cornerTopLeftCenter, radius: radius, startAngle: topLeftStartAngle, endAngle: topLeftEndAngle, clockwise: false) // Path is set as the shapeLayer object''s path. shapeLayer.path = path; shapeLayer.backgroundColor = UIColor.clear.cgColor shapeLayer.frame = currentFrame shapeLayer.masksToBounds = false shapeLayer.setValue(0, forKey: "isCircle") shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = borderColor.cgColor shapeLayer.lineWidth = CGFloat(borderWidth) shapeLayer.lineDashPattern = [NSNumber(value: dashSize), NSNumber(value: dashSize)] shapeLayer.lineCap = kCALineCapRound self.layer.addSublayer(shapeLayer) self.layer.cornerRadius = radius; }


Esto es si lo quisieras en Swift 2

func addDashedLineBorderWithColor(color:UIColor) { let _ = self.sublayers?.filter({$0.name == "DashedBorder"}).map({$0.removeFromSuperlayer()}) let border = CAShapeLayer(); border.name = "DashedBorder" border.strokeColor = color.CGColor; border.fillColor = nil; border.lineDashPattern = [4, 4]; border.path = UIBezierPath(rect: self.bounds).CGPath border.frame = self.bounds; self.addSublayer(border); }


Otro método si le gustan las subcapas. En el init de su vista personalizada, ponga esto (_border es un ivar):

_border = [CAShapeLayer layer]; _border.strokeColor = [UIColor colorWithRed:67/255.0f green:37/255.0f blue:83/255.0f alpha:1].CGColor; _border.fillColor = nil; _border.lineDashPattern = @[@4, @2]; [self.layer addSublayer:_border];

Y en tus descargas de layouts, pon esto:

_border.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath; _border.frame = self.bounds;


Para aquellos de ustedes que trabajan en Swift, esta extensión de clase en UIView lo hace fácil. Esto se basó en la respuesta de sunshineDev.

extension UIView { func addDashedBorder() { let color = UIColor.red.cgColor let shapeLayer:CAShapeLayer = CAShapeLayer() let frameSize = self.frame.size let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: frameSize.height) shapeLayer.bounds = shapeRect shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2) shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = color shapeLayer.lineWidth = 2 shapeLayer.lineJoin = kCALineJoinRound shapeLayer.lineDashPattern = [6,3] shapeLayer.path = UIBezierPath(roundedRect: shapeRect, cornerRadius: 5).cgPath self.layer.addSublayer(shapeLayer) } }

Para usarlo:

anyView.addDashedBorder()


Para el borde punteado / punteado de Xamarin.iOS.

dottedLayer = new CAShapeLayer(); dottedLayer.StrokeColor = UIColor.FromRGB(202, 202, 208).CGColor; dottedLayer.FillColor = null; dottedLayer.LineDashPattern = new[] { new NSNumber(4), new NSNumber(2) }; dottedLayer.Path = UIBezierPath.FromRect(YourView.Bounds).CGPath; //for square dottedLayer.Path = UIBezierPath.FromRoundedRect(YourView.Bounds, 5).CGPath; //for rounded corners dottedLayer.Frame = YourView.Bounds; YourView.Layer.AddSublayer(dottedLayer);


Para esto necesitas agregar CAShapeLayer para ese objeto en particular

CAShapeLayer * dotborder = [CAShapeLayer layer]; dotborder.strokeColor = [UIColor redColor].CGColor;//your own color dotborder.fillColor = nil; dotborder.lineDashPattern = @[@4, @2];//your own patten [codeBtn.layer addSublayer:dotborder]; dotborder.path = [UIBezierPath bezierPathWithRect:codeBtn.bounds].CGPath; dotborder.frame = codeBtn.bounds;


Puede establecer el borde con este patrón usando la ruta Layer y Bizer como en los ejemplos a continuación.

C objetivo

CAShapeLayer *yourViewBorder = [CAShapeLayer layer]; yourViewBorder.strokeColor = [UIColor blackColor].CGColor; yourViewBorder.fillColor = nil; yourViewBorder.lineDashPattern = @[@2, @2]; yourViewBorder.frame = yourView.bounds; yourViewBorder.path = [UIBezierPath bezierPathWithRect:yourView.bounds].CGPath; [yourView.layer addSublayer:yourViewBorder];

Swift 3.1

var yourViewBorder = CAShapeLayer() yourViewBorder.strokeColor = UIColor.black.cgColor yourViewBorder.lineDashPattern = [2, 2] yourViewBorder.frame = yourView.bounds yourViewBorder.fillColor = nil yourViewBorder.path = UIBezierPath(rect: yourView.bounds).cgPath yourView.layer.addSublayer(yourViewBorder)

También puede establecer diferentes tipos de diseño utilizando una imagen de patrón como en el ejemplo siguiente.

[yourView.layer setBorderWidth:5.0]; [yourView.layer setBorderColor:[[UIColor colorWithPatternImage:[UIImage imageNamed:@"DotedImage.png"]] CGColor]];///just add image name and create image with dashed or doted drawing and add here

Aquí debe agregar el <QuartzCore/QuartzCore> en el proyecto e importarlo con la línea siguiente en el archivo YourViewController.m .

#import <QuartzCore/QuartzCore.h>


Simplemente puede crear una clase IBDesignable como esta:

import UIKit @IBDesignable class BorderedView: UIView { @IBInspectable var cornerRadius: CGFloat = 0 @IBInspectable var borderWidth: CGFloat = 0 @IBInspectable var borderColor: UIColor = UIColor.clear override func draw(_ rect: CGRect) { let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) path.lineWidth = borderWidth borderColor.setStroke() let dashPattern : [CGFloat] = [10, 4] path.setLineDash(dashPattern, count: 2, phase: 0) path.stroke() } }

Luego solo subclasifica tu vista con BorcedView de Xcode. ¡De esta manera puede establecer el color del borde y el ancho del borde muy fácilmente desde el constructor de interfaz!


Sobre la base de lo que Prasad G ha sugerido, creé un método dentro de una clase UIImage Extras con lo siguiente:

- (CAShapeLayer *) addDashedBorderWithColor: (CGColorRef) color { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; CGSize frameSize = self.size; CGRect shapeRect = CGRectMake(0.0f, 0.0f, frameSize.width, frameSize.height); [shapeLayer setBounds:shapeRect]; [shapeLayer setPosition:CGPointMake( frameSize.width/2,frameSize.height/2)]; [shapeLayer setFillColor:[[UIColor clearColor] CGColor]]; [shapeLayer setStrokeColor:color]; [shapeLayer setLineWidth:5.0f]; [shapeLayer setLineJoin:kCALineJoinRound]; [shapeLayer setLineDashPattern: [NSArray arrayWithObjects:[NSNumber numberWithInt:10], [NSNumber numberWithInt:5], nil]]; UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:shapeRect cornerRadius:15.0]; [shapeLayer setPath:path.CGPath]; return shapeLayer; }

Es importante señalar que si defines la posición de tu forma como (0,0), la esquina inferior del borde se colocará en el centro de la imagen, por eso lo configuré en: (frameSize.width / 2, frameSize .height / 2)

Luego uso mi método para obtener el borde punteado usando el UIImage de mi UIImageView y agrego CAShapeLayer como una subcapa de la capa UIImageView:

[myImageView.layer addSublayer:[myImageView.image addDashedBorderWithColor:[[UIColor whiteColor] CGColor]]];


Solución Swift con clase personalizada trabajada con autolayout

personalizado de @Iin Smith

class DashedBorderView: UIView { @IBInspectable var cornerRadius: CGFloat = 4 @IBInspectable var borderColor: UIColor = UIColor.black @IBInspectable var dashPaintedSize: Int = 2 @IBInspectable var dashUnpaintedSize: Int = 2 let dashedBorder = CAShapeLayer() override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } private func commonInit() { //custom initialization self.layer.addSublayer(dashedBorder) applyDashBorder() } override func layoutSublayers(of layer: CALayer) { super.layoutSublayers(of: layer) applyDashBorder() } func applyDashBorder() { dashedBorder.strokeColor = borderColor.cgColor dashedBorder.lineDashPattern = [NSNumber(value: dashPaintedSize), NSNumber(value: dashUnpaintedSize)] dashedBorder.fillColor = nil dashedBorder.cornerRadius = cornerRadius dashedBorder.path = UIBezierPath(rect: self.bounds).cgPath dashedBorder.frame = self.bounds } }


Terminé creando un IB Designable usando parte de la implementación de @Chris:

CurvedDashedBorderUIVIew.h:

#import <UIKit/UIKit.h> IB_DESIGNABLE @interface CurvedDashedBorderUIVIew : UIView @property (nonatomic) IBInspectable CGFloat cornerRadius; @property (nonatomic) IBInspectable UIColor *borderColor; @property (nonatomic) IBInspectable int dashPaintedSize; @property (nonatomic) IBInspectable int dashUnpaintedSize; @property (strong, nonatomic) CAShapeLayer *border; @end

CurvedDashedBorderUIVIew.m:

#import "CurvedDashedBorderUIVIew.h" @implementation CurvedDashedBorderUIVIew - (instancetype)init { self = [super init]; if (self) { [self setup]; } return self; } - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self setup]; } return self; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setup]; } return self; } -(void)setup { _border = [CAShapeLayer layer]; [self.layer addSublayer:_border]; } -(void)layoutSubviews { [super layoutSubviews]; self.layer.cornerRadius = self.cornerRadius; _border.strokeColor = self.borderColor.CGColor; _border.fillColor = nil; _border.lineDashPattern = @[[NSNumber numberWithInt:_dashPaintedSize], [NSNumber numberWithInt:_dashUnpaintedSize]]; _border.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.cornerRadius].CGPath; _border.frame = self.bounds; } @end

luego simplemente configúralo en el xib / storyboard:


Use el método CGContextSetLineDash ().

CGFloat dashPattern[]= {3.0, 2}; context =UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); // And draw with a blue fill color CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0); // Draw them with a 2.0 stroke width so they are a bit more visible. CGContextSetLineWidth(context, 4.0); CGContextSetLineDash(context, 0.0, dashPattern, 2); CGContextAddRect(context, self.bounds); // Close the path CGContextClosePath(context); CGContextStrokePath(context); // Fill & stroke the path CGContextDrawPath(context, kCGPathFillStroke);

Creo que será útil para ti.


Versión rápida de la respuesta de QuartzCore.

import QuartzCore let dottedPattern = UIImage(named: "dottedPattern") myView.layer.borderWidth = 1 myView.layer.borderColor = UIColor(patternImage: dottedPattern!).CGColor

El enfoque CAShapeLayer funciona, pero el enfoque QuartzCore es mejor para manejar una recarga de Vista de tabla, si el UIView está dentro de una celda.

Para la imagen, puedes usar algo como esto (es realmente pequeño):

Tiendo a preferir el vector a los PNG cuando puedo salirse con la suya:

  • Dentro de Sketch, crea un rectángulo de 4x4 píxeles.
  • Haga un total de cuatro de estos
  • Agrúpalos en una foursquare, alternando colores
  • Exportar el grupo como PDF
  • En Images.xcassets , cree un New Image Set llamado dottedPattern
  • Cambiar los Scale Factors a un Single Vector
  • Suelta tu PDF

prueba el código abajo

- (void)drawRect:(CGRect)rect { //// Color Declarations UIColor* fillColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1]; UIColor* strokeColor = [UIColor colorWithRed: 0.29 green: 0.565 blue: 0.886 alpha: 1]; //// Rectangle Drawing UIBezierPath* rectanglePath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius: 6]; [fillColor setFill]; [rectanglePath fill]; [strokeColor setStroke]; rectanglePath.lineWidth = 1; CGFloat rectanglePattern[] = {6, 2, 6, 2}; [rectanglePath setLineDash: rectanglePattern count: 4 phase: 0]; [rectanglePath stroke]; [super drawRect:rect]; }

para uno como el bramido


Swift 3 :

import UIKit class UIViewWithDashedLineBorder: UIView { override func draw(_ rect: CGRect) { let path = UIBezierPath(roundedRect: rect, cornerRadius: 0) UIColor.purple.setFill() path.fill() UIColor.orange.setStroke() path.lineWidth = 5 let dashPattern : [CGFloat] = [10, 4] path.setLineDash(dashPattern, count: 2, phase: 0) path.stroke() } }

Usar en un guión gráfico (como clase personalizada) o directamente en el código:

let v = UIViewWithDashedLineBorder(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

Resultado:


extension UIView{ func addDashedLineBorder() { let color = UIColor.black.cgColor let shapeLayer:CAShapeLayer = CAShapeLayer() let frameSize = (self.frame.size) let shapeRect = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) shapeLayer.bounds = shapeRect shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2) shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = color shapeLayer.lineWidth = 1 shapeLayer.lineJoin = kCALineJoinRound shapeLayer.lineDashPattern = [2,2] shapeLayer.path = UIBezierPath(rect: shapeRect).cgPath self.layer.addSublayer(shapeLayer) }

} y llama a esta función en viewdidLoad () con retraso:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // Your code with delay self.YourView.addDashedBorder() }