let block = UIView(frame: CGRectMake(cellWidth-25, cellHeight/2-8, 16, 16))
block.backgroundColor = UIColor(netHex: 0xff3b30)
block.layer.cornerRadius = 9
block.clipsToBounds = true
C'est ce que j'ai pour le moment, mais ce n'est évidemment pas la bonne façon de le faire.
Quel est le moyen le plus simple de le faire?
Vous pouvez dessiner un cercle avec ceci:
Swift 2.2:
let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100,y: 100), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.CGPath
//change the fill color
shapeLayer.fillColor = UIColor.clearColor().CGColor
//you can change the stroke color
shapeLayer.strokeColor = UIColor.redColor().CGColor
//you can change the line width
shapeLayer.lineWidth = 3.0
view.layer.addSublayer(shapeLayer)
Swift 3.0:
let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100,y: 100), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
//change the fill color
shapeLayer.fillColor = UIColor.clear.cgColor
//you can change the stroke color
shapeLayer.strokeColor = UIColor.red.cgColor
//you can change the line width
shapeLayer.lineWidth = 3.0
view.layer.addSublayer(shapeLayer)
Avec le code que vous avez posté, vous coupez les coins de UIView sans ajouter de cercle à la vue.
Voici un exemple complet d'utilisation de cette méthode:
// make the UIView a ring of color
import UIKit
class Ring:UIView
{
override func drawRect(rect: CGRect)
{
drawRingFittingInsideView()
}
internal func drawRingFittingInsideView()->()
{
let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2)
let desiredLineWidth:CGFloat = 1 // your desired value
let circlePath = UIBezierPath(
arcCenter: CGPoint(x:halfSize,y:halfSize),
radius: CGFloat( halfSize - (desiredLineWidth/2) ),
startAngle: CGFloat(0),
endAngle:CGFloat(M_PI * 2),
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = UIColor.redColor().CGColor
shapeLayer.lineWidth = desiredLineWidth
layer.addSublayer(shapeLayer)
}
}
Notez cependant qu'il y a un appel incroyablement pratique
qui fait tout le travail de faire le chemin. (N'oubliez pas de l'insérer pour l'épaisseur du trait, ce qui est également incroyablement facile avec CGRectInset
.)
internal func drawRingFittingInsideView(rect: CGRect)->()
{
let desiredLineWidth:CGFloat = 4 // your desired value
let hw:CGFloat = desiredLineWidth/2
let circlePath = UIBezierPath(ovalInRect: CGRectInset(rect,hw,hw) )
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = UIColor.redColor().CGColor
shapeLayer.lineWidth = desiredLineWidth
layer.addSublayer(shapeLayer)
}
En pratique ces jours-ci à Swift, vous utiliseriez certainement
et
De cette façon, vous pouvez réellement voir et modifier le rendu dans Storyboard!}
Comme vous pouvez le constater, l'inspecteur sur le storyboard est doté de nouvelles fonctionnalités que vous pouvez modifier sur le storyboard:
Voici le code ...
// Dot with border, which you can control completely in Storyboard
import UIKit
@IBDesignable
class Dot:UIView
{
@IBInspectable var mainColor: UIColor = UIColor.blueColor()
{
didSet { print("mainColor was set here") }
}
@IBInspectable var ringColor: UIColor = UIColor.orangeColor()
{
didSet { print("bColor was set here") }
}
@IBInspectable var ringThickness: CGFloat = 4
{
didSet { print("ringThickness was set here") }
}
@IBInspectable var isSelected: Bool = true
override func drawRect(rect: CGRect)
{
let dotPath = UIBezierPath(ovalInRect:rect)
let shapeLayer = CAShapeLayer()
shapeLayer.path = dotPath.CGPath
shapeLayer.fillColor = mainColor.CGColor
layer.addSublayer(shapeLayer)
if (isSelected) { drawRingFittingInsideView(rect) }
}
internal func drawRingFittingInsideView(rect: CGRect)->()
{
let hw:CGFloat = ringThickness/2
let circlePath = UIBezierPath(ovalInRect: CGRectInset(rect,hw,hw) )
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = ringColor.CGColor
shapeLayer.lineWidth = ringThickness
layer.addSublayer(shapeLayer)
}
}
Enfin, notez que si vous avez une vue UIView (qui est carrée et que vous voulez définir le rouge dans Storyboard) et que vous voulez simplement la transformer en cercle rouge, vous pouvez simplement procéder comme suit:
// It makes a UIView into a circular dot of color
import UIKit
class Dot:UIView
{
override func layoutSubviews()
{ layer.cornerRadius = bounds.size.width/2; }
}
Si vous voulez utiliser UIView pour le dessiner, vous devez définir le rayon/de la hauteur ou de la largeur.
alors changez simplement:
block.layer.cornerRadius = 9
à:
block.layer.cornerRadius = block.frame.width / 2
Cependant, vous aurez besoin de rendre la hauteur et la largeur identiques. Si vous souhaitez utiliser coregraphics, vous voudrez faire quelque chose comme ceci:
CGContextRef ctx= UIGraphicsGetCurrentContext();
CGRect bounds = [self bounds];
CGPoint center;
center.x = bounds.Origin.x + bounds.size.width / 2.0;
center.y = bounds.Origin.y + bounds.size.height / 2.0;
CGContextSaveGState(ctx);
CGContextSetLineWidth(ctx,5);
CGContextSetRGBStrokeColor(ctx,0.8,0.8,0.8,1.0);
CGContextAddArc(ctx,locationOfTouch.x,locationOfTouch.y,30,0.0,M_PI*2,YES);
CGContextStrokePath(ctx);
Créez une classe UIView et attribuez-lui ce code pour un simple cercle
import UIKit
@IBDesignable
class DRAW: UIView {
override func draw(_ rect: CGRect) {
var path = UIBezierPath()
path = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 100, height: 100))
UIColor.yellow.setStroke()
UIColor.red.setFill()
path.lineWidth = 5
path.stroke()
path.fill()
}
}
Mise à jour de l'approche de code de @ Dario pour Xcode 8.2.2, Swift 3.x. Notez que dans le storyboard, définissez la couleur d'arrière-plan sur "clear" pour éviter un arrière-plan noir dans le carré UIView:
import UIKit
@IBDesignable
class Dot:UIView
{
@IBInspectable var mainColor: UIColor = UIColor.clear
{
didSet { print("mainColor was set here") }
}
@IBInspectable var ringColor: UIColor = UIColor.clear
{
didSet { print("bColor was set here") }
}
@IBInspectable var ringThickness: CGFloat = 4
{
didSet { print("ringThickness was set here") }
}
@IBInspectable var isSelected: Bool = true
override func draw(_ rect: CGRect)
{
let dotPath = UIBezierPath(ovalIn: rect)
let shapeLayer = CAShapeLayer()
shapeLayer.path = dotPath.cgPath
shapeLayer.fillColor = mainColor.cgColor
layer.addSublayer(shapeLayer)
if (isSelected) { drawRingFittingInsideView(rect: rect) }
}
internal func drawRingFittingInsideView(rect: CGRect)->()
{
let hw:CGFloat = ringThickness/2
let circlePath = UIBezierPath(ovalIn: rect.insetBy(dx: hw,dy: hw) )
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = ringColor.cgColor
shapeLayer.lineWidth = ringThickness
layer.addSublayer(shapeLayer)
}
}
Et si vous voulez contrôler les angles de début et de fin:
import UIKit
@IBDesignable
class Dot:UIView
{
@IBInspectable var mainColor: UIColor = UIColor.clear
{
didSet { print("mainColor was set here") }
}
@IBInspectable var ringColor: UIColor = UIColor.clear
{
didSet { print("bColor was set here") }
}
@IBInspectable var ringThickness: CGFloat = 4
{
didSet { print("ringThickness was set here") }
}
@IBInspectable var isSelected: Bool = true
override func draw(_ rect: CGRect)
{
let dotPath = UIBezierPath(ovalIn: rect)
let shapeLayer = CAShapeLayer()
shapeLayer.path = dotPath.cgPath
shapeLayer.fillColor = mainColor.cgColor
layer.addSublayer(shapeLayer)
if (isSelected) { drawRingFittingInsideView(rect: rect) }
}
internal func drawRingFittingInsideView(rect: CGRect)->()
{
let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2)
let desiredLineWidth:CGFloat = ringThickness // your desired value
let circlePath = UIBezierPath(
arcCenter: CGPoint(x: halfSize, y: halfSize),
radius: CGFloat( halfSize - (desiredLineWidth/2) ),
startAngle: CGFloat(0),
endAngle:CGFloat(Double.pi),
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = ringColor.cgColor
shapeLayer.lineWidth = ringThickness
layer.addSublayer(shapeLayer)
}
}
Swift 4 version de la réponse acceptée:
@IBDesignable
class CircledDotView: UIView {
@IBInspectable var mainColor: UIColor = .white {
didSet { print("mainColor was set here") }
}
@IBInspectable var ringColor: UIColor = .black {
didSet { print("bColor was set here") }
}
@IBInspectable var ringThickness: CGFloat = 4 {
didSet { print("ringThickness was set here") }
}
@IBInspectable var isSelected: Bool = true
override func draw(_ rect: CGRect) {
let dotPath = UIBezierPath(ovalIn: rect)
let shapeLayer = CAShapeLayer()
shapeLayer.path = dotPath.cgPath
shapeLayer.fillColor = mainColor.cgColor
layer.addSublayer(shapeLayer)
if (isSelected) {
drawRingFittingInsideView(rect: rect)
}
}
internal func drawRingFittingInsideView(rect: CGRect) {
let hw: CGFloat = ringThickness / 2
let circlePath = UIBezierPath(ovalIn: rect.insetBy(dx: hw, dy: hw))
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = ringColor.cgColor
shapeLayer.lineWidth = ringThickness
layer.addSublayer(shapeLayer)
}
}
Je trouve que Core Graphics est assez simple pour Swift 3 :
if let cgcontext = UIGraphicsGetCurrentContext() {
cgcontext.strokeEllipse(in: CGRect(x: center.x-diameter/2, y: center.y-diameter/2, width: diameter, height: diameter))
}
Une approche beaucoup plus facile et conviviale serait.
import UIKit
@IBDesignable
class CircleDrawView: UIView {
@IBInspectable var borderColor: UIColor = UIColor.red;
@IBInspectable var borderSize: CGFloat = 4
override func draw(_ rect: CGRect)
{
layer.borderColor = borderColor.cgColor
layer.borderWidth = borderSize
layer.cornerRadius = self.frame.height/2
}
}
Avec Border Color
et Border Size
et la propriété par défaut Background
, vous pouvez définir l'apparence du cercle.
Veuillez noter que pour dessiner un cercle, la hauteur et la largeur de la vue doivent être de taille égale.
Le code fonctionne pour Swift >= 4
et Xcode >= 9
.
Ajouter dans la vue a chargé
//Circle Points
var CircleLayer = CAShapeLayer()
let center = CGPoint (x: myCircleView.frame.size.width / 2, y: myCircleView.frame.size.height / 2)
let circleRadius = myCircleView.frame.size.width / 2
let circlePath = UIBezierPath(arcCenter: center, radius: circleRadius, startAngle: CGFloat(M_PI), endAngle: CGFloat(M_PI * 4), clockwise: true)
CircleLayer.path = circlePath.cgPath
CircleLayer.strokeColor = UIColor.red.cgColor
CircleLayer.fillColor = UIColor.blue.cgColor
CircleLayer.lineWidth = 8
CircleLayer.strokeStart = 0
CircleLayer.strokeEnd = 1
Self.View.layer.addSublayer(CircleLayer)
Une simple fonction dessinant un cercle au milieu du cadre de votre fenêtre, en utilisant un pourcentage de multiplicateur
/// CGFloat is a multiplicator from self.view.frame.width
func drawCircle(withMultiplicator coefficient: CGFloat) {
let radius = self.view.frame.width / 2 * coefficient
let circlePath = UIBezierPath(arcCenter: self.view.center, radius: radius, startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
//change the fill color
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.darkGray.cgColor
shapeLayer.lineWidth = 2.0
view.layer.addSublayer(shapeLayer)
}