https://kotlinlang.org logo
#ios
Title
# ios
r

ribesg

08/20/2021, 10:11 AM
So it’s probably a long shot as I sometimes feel like I’m the only one doing UIKit in Kotlin, but does anyone know if there’s a know bug or trick with
CAGradientLayer
in Kotlin/Native? I really can’t get it to work even on a simple view and I feel like I checked all the problems people usually encounter when using it in ObjC/Swift
t

Thomas

08/20/2021, 11:06 AM
I am using CAGradientLayer in Kotlin and it is working fine for me. What exactly is the issue?
I'm using it to create a CALayer which I then convert to a UIImage.
This is the code which works for me now:
Copy code
internal actual fun createGradientImage(
    colors: List<Color>,
    positions: List<Float>?,
    width: Int,
    height: Int
): UIImage {
    val layer = CAGradientLayer()
    layer.type = kCAGradientLayerConic
    layer.colors = colors.map { CFBridgingRelease(CFRetain(it.toUIColor().CGColor)) }
    positions?.let { layer.locations = it }
    layer.frame = CGRectMake(0.0, 0.0, width.toDouble(), height.toDouble())
    layer.startPoint = CGPointMake(0.5, 0.5)
    layer.endPoint = CGPointMake(1.0, 0.5)
    return imageFromLayer(layer)
}

private fun imageFromLayer(layer: CALayer): UIImage {
    layer.frame.useContents {
        UIGraphicsBeginImageContextWithOptions(this.size.readValue(), false, UIScreen.mainScreen.scale)

        layer.renderInContext(UIGraphicsGetCurrentContext())
        val outputImage = UIGraphicsGetImageFromCurrentImageContext()!!

        UIGraphicsEndImageContext()

        return outputImage
    }
}
r

ribesg

08/20/2021, 11:41 AM
I saw the solution of making an Image but didn’t try it yet. You’re supposed to be able to just have a gradient layer as a sublayer and it should work. Di you try that or did you go straight to the UIImage?
I read your link, so yeah you had the same issue and the explanation is that we need bridging. I’m using bridging in a few places but it’s usually tricky. I’ll try briding for a few minutes but I guess I’ll end up using an UIImageView. Thanks
Yeah. This kind of stuff just works.
Copy code
CAGradientLayer().apply {
        colors = listOf(
            CFBridgingRelease(UIColor.redColor.CGColor),
            CFBridgingRelease(UIColor.greenColor.CGColor)
        )
    }
Now I just need to fix the usual problem of layers not being updated by autolayout, but that’s it. Thanks @Thomas
t

Thomas

08/20/2021, 12:03 PM
Great to hear
For my use case I needed a UIImage so that's why the code converts it.
s

Sam

08/20/2021, 1:35 PM
Keeping layer sizes in sync is a pain. If your view only has one layer, you can create a uiview subclass that creates the gradient layer as it’s primary layer. Then it will stay in sync automatically. If not, you’ll have to do it yourself. I usually override the bounds property and do it there. I’m not sure if that's the best way though.