【发布时间】:2015-03-26 13:17:46
【问题描述】:
我有一个带有填充颜色的 CAShapeLayer,并且想在这个形状的中心添加一个图标:
var shape = CAShapeLayer()
shape.fillColor = UIColor(white: 0.90, alpha: 1).CGColor
var image = UIImage(named: "some_image")
shape.contents = image?.CGImage
此代码确实编译并显示灰色形状 - 但没有图像。 :(
我查看了这些帖子,但我无法像他们那样投射 CGImage。
add UIImage in CALayer 和 Display an image or UIImage with a plain CALayer
还有其他方法吗?还是 id cast 的解决方法?
完整代码:
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)
}
}
}
感兴趣的行在自定义 UIControl 底部的注释下:
“给按钮添加图标和标签”
【问题讨论】:
-
为什么你希望图层在填充颜色上绘制图像?尝试向该图层添加子图层并将图像添加到该图层。
-
不,我试过了,但还是没有画出来... :(
-
你能显示你正在使用的代码吗?没有理由不画画。对于 CALayers,您需要适当地设置边界。
-
感谢@JackWu,如果您想在自己的项目中尝试,我上传了整个课程。 :) 希望你能帮忙!
标签: swift ios8 uiimage cgimage cashapelayer