ich würde vorschlagen, dass Sie nicht wollen, „transparent“ Text. Stattdessen sollten Sie dies als eine weiße Ansicht mit einer "Maske" betrachten, die den Umriss des Textes darstellt und es ermöglicht, das darunter liegende Bild zu enthüllen. Dies ist ein wenig kompliziert, weil die Maske tatsächlich invertiert wird, wie wir Bilder im Allgemeinen maskieren (z. B. ist der Text "Mit Facebook anmelden" nicht die Maske, sondern der weiße Raum um sie herum). Aber Core Graphics bietet Möglichkeiten, dies sehr einfach zu tun.
So, während es wahrscheinlich am einfachsten diese Grafik in Ihrem bevorzugten Bildbearbeitungstool zu erstellen, wenn Sie es programmatisch tun wollen, könnte man so etwas wie die folgende in Swift 3 oder später tun:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let image1 = maskedImage(size: button1.bounds.size, text: "Sign in with Facebook")
button1.setImage(image1, for: .normal)
let image2 = maskedImage(size: button2.bounds.size, text: "Sign-up with Email")
button2.setImage(image2, for: .normal)
}
func maskedImage(size: CGSize, text: String) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, true, 0)
let context = UIGraphicsGetCurrentContext()
context?.scaleBy(x: 1, y: -1)
context?.translateBy(x: 0, y: -size.height)
// draw rounded rectange inset of the button's entire dimensions
UIColor.white.setStroke()
let pathRect = CGRect(origin: .zero, size: size).insetBy(dx: 10, dy: 10)
let path = UIBezierPath(roundedRect: pathRect, cornerRadius: 5)
path.lineWidth = 4
path.stroke()
// draw the text
let attributes: [NSAttributedStringKey: Any] = [
.font: UIFont.preferredFont(forTextStyle: .caption1),
.foregroundColor: UIColor.white
]
let textSize = text.size(withAttributes: attributes)
let point = CGPoint(x: (size.width - textSize.width)/2, y: (size.height - textSize.height)/2)
text.draw(at: point, withAttributes: attributes)
// capture the image and end context
let maskImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// create image mask
guard let cgimage = maskImage?.cgImage, let dataProvider = cgimage.dataProvider else { return nil }
let bytesPerRow = cgimage.bytesPerRow
let bitsPerPixel = cgimage.bitsPerPixel
let width = cgimage.width
let height = cgimage.height
let bitsPerComponent = cgimage.bitsPerComponent
guard let mask = CGImage(maskWidth: width, height: height, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow: bytesPerRow, provider: dataProvider, decode: nil, shouldInterpolate: false) else { return nil }
// create the actual image
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
UIGraphicsGetCurrentContext()?.clip(to: rect, mask: mask)
UIColor.white.withAlphaComponent(0.9).setFill()
UIBezierPath(rect: rect).fill()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// return image
return image
}
Die Technik, auf die hier zu achten ist, ist die Verwendung von CGImage(maskWidth:...)
, mit der wir eine Bildmaske erstellen können, außer dem weißen Text und der Grenze, die wir gezeichnet haben. Wenn wir dann das endgültige Bild erstellen, können wir es mit clip(to:mask:)
an diese "Bildmaske" anhängen.Wenn wir über das Maskieren von Bildern sprechen, maskieren wir sie im Allgemeinen mit UIBezierRect
oder anderen Bildern (wo ein Alpha-Kanal ungleich null anzeigt, was maskiert werden soll und was nicht). Aber hier maskieren wir eine "Image Mask" von Core Graphics, die uns mehr Kontrolle gibt. Eine Erläuterung der Unterschiede zwischen der Maskierung mit einer Bildmaske und der Maskierung mit einem Bild finden Sie im Kapitel Masking Images des Quartz 2D-Programmierhandbuchs .
Für Swift 2-Wiedergabe siehe previous revision of this answer.
Es wäre hilfreich zu sehen, was Ihr Code tatsächlich visuell produziert. –