How to draw a UILabel with a different blend mode in draw(_ rect: CGRect) in Swift

一曲冷凌霜 提交于 2019-12-07 18:08:59

问题


So I have a UILabel that is being drawn on top of a gradient image (that is a UIImageView). It looks sorta like this:

I'm trying to change the blendMode of the graphics context in the UILabel's draw(_ rect: CGRect) function so that it draws the label but blended with the background with a softLight blending mode.

Here is what I want it to look like:

Here is the code I have in the draw(_ rect: CGRect) function:

override func draw(_ rect: CGRect) {
    // Drawing code
     if let context = UIGraphicsGetCurrentContext() {
        context.setBlendMode(.softLight)
        self.textColor.set()
        self.drawText(in: rect)
   }
 }

This code just renders the top picture and not the blended version. This is not all that I've tried, I've tried so much other things but I just don't understand CGContext's and the draw function in particular.

Most answers on SO are either in old objective-c and are deprecated/broken or swift and too complicated (use Metal for example). I just want to draw the text in the context I have and set the context's blending mode to soft light. There has to be an easy way!

Any help on how to fix this would be appreciated. Thanks!


回答1:


You can't blend views this way; they have separate layer hierarchies that are resolved independently. Move the gradient and text on CALayer objects and blend those (or draw them by hand inside the same view). For example:

class MyView: UIView {
    let gradientLayer: CAGradientLayer = {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [UIColor.red.cgColor,
                                UIColor.blue.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        return gradientLayer
    }()

    let textLayer: CATextLayer = {
        let textLayer = CATextLayer()
        let astring = NSAttributedString(string: "Text Example",
                                         attributes: [.font: UIFont(name: "MarkerFelt-Wide", size: 60)!])
        textLayer.string = astring
        textLayer.alignmentMode = kCAAlignmentCenter
        textLayer.bounds = astring.boundingRect(with: CGSize(width: .max, height: .max),
                                                options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
        return textLayer
    }()

    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            gradientLayer.bounds = bounds
            gradientLayer.render(in: context)

            context.saveGState()
            context.setBlendMode(.softLight)

            context.translateBy(x: center.x - textLayer.bounds.width / 2,
                                y: center.y - textLayer.bounds.height / 2)

            textLayer.position = center
            textLayer.render(in: context)
            context.restoreGState()
        }
    }
}




回答2:


So in case your text is really a label you could try it with changing the opacity like for normal labels. I assume you're familiar with setting an alpha to a label. Please find below one example for setting an alpha for a label:

label.textColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.25)

Please give me a hint, if it's not a label - then it should be more complicated.



来源:https://stackoverflow.com/questions/46865660/how-to-draw-a-uilabel-with-a-different-blend-mode-in-draw-rect-cgrect-in-swi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!