2015-03-26 1 views
1

J'ai un CAShapeLayer avec une couleur de remplissage, et que vous souhaitez ajouter une icône dans le centre de cette forme:Swift: Ajouter une image à CAShapeLayer

var shape = CAShapeLayer() 
shape.fillColor = UIColor(white: 0.90, alpha: 1).CGColor 
var image = UIImage(named: "some_image") 
shape.contents = image?.CGImage 

Ce code ne compile et ne montre la forme- gris, mais pas d'image. :(

J'ai regardé dans ces messages, mais je ne peux pas jeter le CGImage comme ils le font.

add UIImage in CALayer et Display an image or UIImage with a plain CALayer

Y at-il une autre façon? Ou une solution à la distribution id?

code complet:

ViewController.swift

import UIKit 

class ViewController: UIViewController { 

    @IBOutlet var menuView: UIView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func viewDidAppear(animated: Bool) { 

     let menu: CircularMenu = CircularMenu(frame: menuView.bounds, numberOfMenuItems: 4, hasProgressBar: false) 
     self.menuView.addSubview(menu) 
    } 

} 

CircularMenu.swift

import UIKit 

// *** Helper methods start 
func DegreesToRadians (value: Double) -> CGFloat { 
    return CGFloat(value * M_PI/180.0) 
} 

func RadiansToDegrees (value: Double) -> CGFloat { 
    return CGFloat(value * 180.0/M_PI) 
} 
// *** Helper methods end 

class CircularMenu: UIControl { 

    var parent: UIViewController! 

    var centerButton: UIButton! 
    var menuButtonShapes = [CAShapeLayer]() 
    var menuButtons = [UIButton]() 

    var numberOfButtons: Double = 4 

    var bigSize: CGFloat = 300 
    var centerButtonSize: CGFloat = 100 
    var centerButtonPadding: CGFloat = 70 
    let paddingBetweenButtons = 1 

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

    override init(frame: CGRect) { 
     super.init(frame: frame) 
    } 

    convenience init(frame: CGRect, numberOfMenuItems: Int, hasProgressBar: Bool = false) { 
     self.init(frame: frame) 
     self.bounds = frame 

     self.bigSize = frame.width 
     self.centerButtonSize = bigSize/2 
     self.centerButtonPadding = bigSize/4-5 

     if hasProgressBar { 
      self.centerButtonSize -= 10 
     } 

     if numberOfMenuItems != 0 && numberOfMenuItems <= 10 { 
      self.numberOfButtons = Double(numberOfMenuItems) 
     } 

     // Draw center button 
     var centerButtonView = UIView(frame: CGRectMake(0, 0, centerButtonSize, centerButtonSize)) 
     centerButtonView.backgroundColor = UIColor(red: 160.0/255, green: 197.0/255, blue: 25.0/255, alpha: 1) 

     centerButtonView.center = self.center; 
     centerButtonView.layer.cornerRadius = centerButtonSize/2 
     self.addSubview(centerButtonView) 
     self.centerButton = UIButton(frame: centerButtonView.bounds) 


     let degreesPerButton: Double = 360.0/numberOfButtons 

     // Draw button shapes 
     for (var i: Double = 1; i <= numberOfButtons; i++) 
     { 
      // Determine start and end radians of pizza slice 
      let startAngle = DegreesToRadians(degreesPerButton*i+degreesPerButton-Double(paddingBetweenButtons)) 
      let endAngle = DegreesToRadians(degreesPerButton*i+Double(paddingBetweenButtons)) 

      // Determine center and angle of slice 
      var buttonCenter = self.center; 
      var offsetDirection = (startAngle - endAngle)/2 + endAngle 

      // Shove slice outward to make space for inner padding 
      var offsetX = cos(offsetDirection)*tan(DegreesToRadians(Double(paddingBetweenButtons)))*bigSize/2 
      var offsetY = sin(offsetDirection)*tan(DegreesToRadians(Double(paddingBetweenButtons)))*bigSize/2 

      buttonCenter.x += offsetX 
      buttonCenter.y += offsetY 

      // Create mask for outer rim of slice to a circular form (from triangle to pizza slice) 
      let outerCircleRadius = bigSize/2; 
      var bigCircle = UIBezierPath(arcCenter: self.center, radius: bigSize/2, startAngle: startAngle , endAngle: endAngle, clockwise: false); 
      bigCircle.addLineToPoint(buttonCenter) 
      bigCircle.closePath() 

      // Take padding into consideration when creating mask 
      let tmpBigSizeX = (bigSize+2*abs(offsetX)) 
      let tmpBigSizeY = (bigSize+2*abs(offsetY)) 

      // Create mask for inner rim of slice to a circular form (from pizza slice to donut slice) 
      let smallSize = bigSize-centerButtonSize-centerButtonPadding 
      let innerCircleRadius = outerCircleRadius-bigSize/2/2; 
      var smallCircle = UIBezierPath(arcCenter: self.center, radius: smallSize, startAngle: 0 , endAngle: DegreesToRadians(360), clockwise: false); 

      // Apply masks for everything but the donut slice shape 
      var buttonShape = CAShapeLayer() 
      var maskLayer = CAShapeLayer() 
      var maskPath = CGPathCreateMutable(); 

      CGPathAddRect(maskPath, nil, CGRectMake(outerCircleRadius-tmpBigSizeX/2, outerCircleRadius-tmpBigSizeY/2, tmpBigSizeX, tmpBigSizeY)); 
      CGPathAddPath(maskPath, nil, smallCircle.CGPath); 
      maskLayer.path = maskPath; 
      maskLayer.fillRule = kCAFillRuleEvenOdd; 

      buttonShape.path = bigCircle.CGPath 
      buttonShape.mask = maskLayer 
      buttonShape.fillColor = UIColor(white: 0.90, alpha: 1).CGColor 

      // Add icons and labels to the button 
      var image = UIImage(named: "menu-icon_users_grey") 
      let imageSubLayer = CALayer() 
      imageSubLayer.contents = image?.CGImage 
      buttonShape.addSublayer(imageSubLayer) 

      // Save references to both shape and button 
      self.menuButtons.append(UIButton(frame: buttonShape.frame)) 
      self.menuButtonShapes.append(buttonShape) 

      // Add shape to view 
      self.layer.addSublayer(buttonShape) 
     } 
    } 

} 

Lignes d'intérêt sont en bas de l'UIControl personnalisé sous le commentaire:

"Ajouter des icônes et des étiquettes sur le bouton"

+0

Pourquoi pensez-vous que la couche dessine l'image sur la couleur de remplissage? Essayez d'ajouter une sous-couche à cette couche et ajoutez l'image à cela. – Jack

+0

Non, j'ai essayé mais il n'est toujours pas dessiné ... :( – Anfaje

+0

Pouvez-vous montrer le code que vous utilisez? Il n'y a pas de raison pour cela de ne pas dessiner.Pour CALayers, vous devez définir les limites de façon appropriée – Jack

Répondre

3

Vous avez deux options:

Le moins bon, transformer l'UIImage en une couleur, puis le transformer en CGColor, mais depuis votre extrait de code est si petit, je ne sais pas ce qui va travailler:

let image = UIImage(named: "") 
if let realImage = image { 
    let color = UIColor(patternImage: realImage) 
    shape.fillColor = color.CGColor 
} 

Et le recommandé, créez un nouveau calque et définissez le UIImage sur son contenu:

let imageSubLayer = CALayer() 
imageSubLayer.contents = image?.CGImage 
shape.addSublayer(imageSubLayer) 

je peux Ne le testez pas maintenant, dites-moi si ça marche.

+0

Nop. La solution recommandée ne fonctionne pas au moins sur TViOS fonctionnant 10.x – user3069232

+0

Je ne le teste pas sur tvOS, mais dans iOS vous devez définir un cadre pour cette imageSublayer afin de travailler – Laszlo