Bordure de ligne pointillée autour de UIView

Réponses:

131

Vous pouvez définir la bordure avec ce modèle en utilisant le chemin de calque et de Bézier comme dans les exemples ci-dessous.

Objectif c

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)

Vous pouvez également définir différents types de conception en utilisant l'image de motif comme l'exemple ci-dessous.

[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

Ici, vous devez ajouter un <QuartzCore/QuartzCore>cadre dans le projet et l'importer avec la ligne ci-dessous dans le YourViewController.mfichier.

#import <QuartzCore/QuartzCore.h>
Paras Joshi
la source
2
ce n'est pas une manière parfaite quand on parle d'iPhone6 ​​plus. La ligne pointillée peut devenir floue.
Jacky
1
@Jacky: utilisez une image de résolution plus élevée. :)
Olie
6
quel exemple de l'image?
Tom Roggero
1
pouvez-vous donner un exemple de l'image?
Jonguo
1
Jonguo Par exemple, si vous ajoutez une image avec une résolution appropriée, comme supposons que votre taille d'image normale soit 120x120 et que son nom soit test.png, créez deux autres images avec le nom [email protected] et [email protected] avec une taille de 240x240 et 360x360 qui est utilisé automatiquement dans tous les appareils Apple avec son nom associé. (c'est-à-dire que test.png est utilisé dans l'iPhone 4, test @ 2x sera utile pour iPhone 4s, 5, 5s, 6, 6s et twst @ 3x sera utile pour iPhone 6 plus, 6s plus.
Paras Joshi
273

Une autre méthode si vous aimez les sous-couches. Dans l'initialisation de votre vue personnalisée, mettez ceci (_border est 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];

Et dans vos layoutsubviews, mettez ceci:

_border.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
_border.frame = self.bounds;
Chris
la source
41
Agréable! Vous pouvez également utiliser quelque chose comme ceci pour un effet arrondi:_border.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:5.f].CGPath;
Everton Cunha
Désolé! Je ne comprends pas. Un exemple? @EvertonCunha
Yi Jiang
3
@VanDuTran Dans le premier extrait,_border.lineWidth = 3
Chris
1
hey j'ai appliqué ce code à l'étiquette sur la cellule de vue de tableau mais il donne une petite taille de bordure comment puis-je corriger cela.
Chaudhary Ankit Deshwal
3
Swift 3: border = CAShapeLayer() border.strokeColor = yourColor border.fillColor = nil border.lineDashPattern = [4, 2] self.layer.addSublayer(border)
Geek20
71

Pour ceux d'entre vous qui travaillent dans Swift, cette extension de classe sur UIView facilite les choses. Ceci était basé sur la réponse 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 = CAShapeLayerLineJoin.round
    shapeLayer.lineDashPattern = [6,3]
    shapeLayer.path = UIBezierPath(roundedRect: shapeRect, cornerRadius: 5).cgPath

    self.layer.addSublayer(shapeLayer)
    }
}

Pour l'utiliser:

anyView.addDashedBorder()
rmooney
la source
2
Super morceau de code! Juste un problème, lorsque je l'applique à une UIImageView, il ne reconnaît pas toute la largeur de celui-ci, il en fait environ 80%.
arielcr
1
Je pense que vous appelez probablement addDashBorder trop tôt, essayez de l'appeler à l'intérieur de didLayoutSubviews
Godfather
3
J'ai créé un UIView personnalisé et mis cette extension à l'intérieur. Ensuite, j'ai appelé addDashedBorder()pendant didMoveToSuperview()que je pensais que la mise en page automatique serait terminée et que la taille du cadre serait correcte, mais ce n'était pas le cas. La largeur de la bordure en pointillés dépasse la largeur de la vue. La ligne en pointillé est si belle au fait! Le self.frame.sizen'est pas correct.
levibostian
self.layer.masksToBounds = true Utilisez ceci s'il sort des limites
Ankish Jain
@rmooney a fonctionné xcellent mais le problème est que lorsque vous ajoutez un sous-calque dans une cellule dynamique UITableView, le calque considéré comme le calque du storyboard et il ne fonctionne pas dans une cellule personnalisée sa taille diffère si votre largeur de storyboard 375px il sera toujours considéré comme la bordure par le même taille et cela ne fonctionnera pas dans un appareil plus grand comme 414px et ainsi de suite.
Azharhussain Shaikh
18

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()
    }
}

Utilisation dans un storyboard (en tant que classe personnalisée) ou directement dans le code:

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

Résultat:

entrez la description de l'image ici

ceinture
la source
Surprise qu'il n'y ait plus de votes positifs à ce sujet. Cette solution fonctionne mieux avec la mise en page automatique par rapport aux autres réponses.
Yuchen Zhong
17

En me basant sur ce que Prasad G a suggéré, j'ai créé une méthode dans une classe UIImage Extras avec les éléments suivants:

- (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;
}

Il est important de souligner que si vous définissez la position de votre forme comme (0,0), le coin inférieur de la bordure sera placé au centre de l'image, c'est pourquoi je l'ai défini sur: (frameSize.width / 2, frameSize .hauteur / 2)

J'utilise ensuite ma méthode pour obtenir la bordure en pointillés à l'aide de l'UIImage de mon UIImageView et j'ajoute CAShapeLayer en tant que sous-couche de la couche UIImageView:

[myImageView.layer addSublayer:[myImageView.image addDashedBorderWithColor:[[UIColor whiteColor] CGColor]]];
soleilDev
la source
16

Utilisez la méthode 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);

Je pense que cela vous sera utile.

Prasad G
la source
1
Quel est le contexte ici?
Avinash Sharma
11

Voici une sous-classe UIView qui peut fonctionner pour n'importe quel projet, elle fonctionne également pour les vues rondes :

import UIKit

class CustomDashedView: UIView {

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var dashWidth: CGFloat = 0
    @IBInspectable var dashColor: UIColor = .clear
    @IBInspectable var dashLength: CGFloat = 0
    @IBInspectable var betweenDashesSpace: CGFloat = 0

    var dashBorder: CAShapeLayer?

    override func layoutSubviews() {
        super.layoutSubviews()
        dashBorder?.removeFromSuperlayer()
        let dashBorder = CAShapeLayer()
        dashBorder.lineWidth = dashWidth
        dashBorder.strokeColor = dashColor.cgColor
        dashBorder.lineDashPattern = [dashLength, betweenDashesSpace] as [NSNumber]
        dashBorder.frame = bounds
        dashBorder.fillColor = nil
        if cornerRadius > 0 {
            dashBorder.path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath
        } else {
            dashBorder.path = UIBezierPath(rect: bounds).cgPath
        }
        layer.addSublayer(dashBorder)
        self.dashBorder = dashBorder
    }
}

De cette façon, vous pouvez modifier à partir du Storyboard comme ceci:

entrez la description de l'image ici

Une paire de résultats:

entrez la description de l'image ici

entrez la description de l'image ici

xavi.pedrals
la source
10

Pour cela, vous devez ajouter CAShapeLayer pour cet objet particulier

 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;
btmanikandan
la source
7

Swift 4.2

Basé sur la réponse de rmooney en tant UIViewqu'extension avec des paramètres configurables avec des valeurs par défaut définies.

Notez que cela ne fonctionne pas si la vue a self.translatesAutoresizingMaskIntoConstraints = false

extension UIView {
  func addDashedBorder(_ color: UIColor = UIColor.black, withWidth width: CGFloat = 2, cornerRadius: CGFloat = 5, dashPattern: [NSNumber] = [3,6]) {

    let shapeLayer = CAShapeLayer()

    shapeLayer.bounds = bounds
    shapeLayer.position = CGPoint(x: bounds.width/2, y: bounds.height/2)
    shapeLayer.fillColor = nil
    shapeLayer.strokeColor = color.cgColor
    shapeLayer.lineWidth = width
    shapeLayer.lineJoin = CAShapeLayerLineJoin.round // Updated in swift 4.2
    shapeLayer.lineDashPattern = dashPattern
    shapeLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath

    self.layer.addSublayer(shapeLayer)
  }
}
Dan Leonard
la source
shapeLayer.lineJoin = CAShapeLayerLineJoin.rounddevrait êtreyourViewBorder.lineJoin = kCALineJoinRound
pw2
6

Version Swift de la réponse QuartzCore.

import QuartzCore    

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

L' CAShapeLayerapproche fonctionne, mais l'approche QuartzCore est meilleure pour gérer un rechargement de vue de table, si le UIViewest à l'intérieur d'une cellule.

Pour l'image, vous pouvez utiliser quelque chose comme ça (c'est vraiment petit):

entrez la description de l'image ici

J'ai tendance à préférer le vecteur aux PNG lorsque je peux m'en tirer:

  • Dans Sketch, créez un rectangle de 4 x 4 pixels.
  • Faites un total de quatre de ces
  • Regroupez-les en un carré en alternant les couleurs
  • Exporter le groupe au format PDF
  • À l'intérieur Images.xcassets, créez unNew Image Set appelé dottedPattern
  • Changer la Scale Factors enSingle Vector
  • Déposez votre PDF
Robert Chen
la source
6

Pour Xamarin.iOS bordure pointillée / pointillée.

        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);
c.lamont.dev
la source
Veuillez élaborer un peu votre réponse au lieu de simplement mettre l'extrait de code.
kabirbaidhya
1
Note pour les futurs lecteurs: vous devez utiliser l'espace de noms CoreAnimation pour utiliser le constructeur CAShapeLayer.
jnel899
6

Dans 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);
ddb
la source
4

C'est si vous le vouliez dans 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);

}
Christos Chadjikyriacou
la source
3

essayez le code ci-dessous

- (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];
}

pour un comme ci-dessous entrez la description de l'image ici

Shabeer Ali
la source
Cornes ne se courbe pas.
Vivek Tyagi
3

Pour Swift 5

extension UIView {
    func addDashBorder() {
        let color = UIColor.white.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.name = "DashBorder"
        shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2)
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = color
        shapeLayer.lineWidth = 1.5
        shapeLayer.lineJoin = .round
        shapeLayer.lineDashPattern = [2,4]
        shapeLayer.path = UIBezierPath(roundedRect: shapeRect, cornerRadius: 10).cgPath

        self.layer.masksToBounds = false

        self.layer.addSublayer(shapeLayer)
    }
}

Comment ajouter

vw.addDashBorder()

Comment supprimer à nouveau la bordure

let _ = vw.layer.sublayers?.filter({$0.name == "DashBorder"}).map({$0.removeFromSuperlayer()})
Hardik Thakkar
la source
2

J'ai fini par créer un IB Designable en utilisant une partie de l'implémentation @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

puis configurez-le simplement dans le xib / storyboard:

entrez la description de l'image ici

Iain Smith
la source
2

Solution Swift avec classe personnalisée fonctionnant avec mise en page automatique

personnalisé de @Iain 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
    }
}
Marosdee Uma
la source
2

Vous pouvez simplement créer une classe IBDesignable comme ceci:

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()
    }

}

Ensuite, sous-classez simplement votre vue avec BorderedView de Xcode. De cette façon, vous pouvez définir la couleur et la largeur de la bordure très facilement à partir du générateur d'interface!

Zahidur Rahman Faisal
la source
2
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)
}

} et appelez cette fonction dans viewdidLoad () avec un délai:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { 
            // Your code with delay
            self.YourView.addDashedBorder()
        }
Ayush Dixit
la source
Cela couvrira la partie 100% de votre vue.
Ayush Dixit
1

• Swift 5

• Fonctionne avec la mise en page automatique

• Fonctionne avec le rayon du coin

import UIKit

    class DashedBorderView: UIView {

    private let dashedLineColor = UIColor.black.cgColor
    private let dashedLinePattern: [NSNumber] = [6, 3]
    private let dashedLineWidth: CGFloat = 4

    private let borderLayer = CAShapeLayer()

    init() {
        super.init(frame: CGRect.zero)

        borderLayer.strokeColor = dashedLineColor
        borderLayer.lineDashPattern = dashedLinePattern
        borderLayer.backgroundColor = UIColor.clear.cgColor
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.lineWidth = dashedLineWidth
        layer.addSublayer(borderLayer)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {
        borderLayer.frame = bounds
        borderLayer.path = UIBezierPath(roundedRect: rect, cornerRadius: layer.cornerRadius).cgPath
    }
}
Skornos
la source
0

Dans swift 4, j'ai créé une extension UIView avec la fonction suivante:

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;
}
Gastón Antonio Montes
la source
0

Si vous voulez que cela fonctionne avec cornerRadius, essayez ceci

tagView.clipsToBounds = YES;
tagView.layer.cornerRadius = 20.0f;
tagView.backgroundColor = [UIColor groupTableViewBackgroundColor];

CAShapeLayer *yourViewBorder = [CAShapeLayer layer];
yourViewBorder.strokeColor = [UIColor blackColor].CGColor;
yourViewBorder.fillColor = nil;
yourViewBorder.lineDashPattern = @[@2, @2];
yourViewBorder.frame = tagView.bounds;

// Create the path for to make circle
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:tagView.bounds
                                               byRoundingCorners:UIRectCornerAllCorners
                                                     cornerRadii:CGSizeMake(20, 20)];


yourViewBorder.path = maskPath.CGPath;

[tagView.layer addSublayer:yourViewBorder];
Clément Joseph
la source
0

Swift 5+

import UIKit

class DashedBorderView: UIView {

    private let borderLayer = CAShapeLayer()

    init(color: UIColor, width: CGFloat = 1) {
        super.init(frame: CGRect.zero)

        let pattern: [NSNumber] = [NSNumber(value: Float(5 * width)), NSNumber(value: Float(3 * width))]

        borderLayer.backgroundColor = nil
        borderLayer.fillColor = nil
        borderLayer.lineDashPattern = pattern
        borderLayer.lineWidth = width
        borderLayer.strokeColor = color.cgColor

        layer.addSublayer(borderLayer)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {
        borderLayer.frame = bounds
        borderLayer.path = UIBezierPath(roundedRect: rect, cornerRadius: layer.cornerRadius).cgPath
    }
}

Comment utiliser:

// f.e. inside UIViewController

let viewWithDashedBorder = DashedBorderView(color: .red, width: 2)
view.addSubview(viewWithDashedBorder)
gondo
la source