6

I've got an image that I made in PaintCode that I want to animate. PaintCode provides a drawing function for UIKit, not SwiftUI. So for testing I can implement it in UIKit with the following VC:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var paintCode: PaintCodeView!
    @IBOutlet weak var slider: UISlider!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func sliderMoved(_ sender: Any) {
        paintCode.progress = CGFloat(slider.value)
    }

}

class PaintCodeView: UIView {

    private var _progress: CGFloat = 0.0

    var progress: CGFloat {
        set {
            if newValue < 0 {
                _progress = 0
            } else if newValue > 1 {
                _progress = 1
            } else {
                _progress = newValue
            }
            setNeedsDisplay()
        }
        get {
            return _progress
        }
    }

    override func draw(_ rect: CGRect) {
        LinkStyles.drawLogoAnimated(frame: self.bounds, resizing: .aspectFit, animationProgress: _progress)
    }

}

Correct animation

But if I try to wrap the same drawing UIView in a UIViewRepresentable to use in SwiftUI, it's not drawing it as expected, instead has a black background and glitching animation.

import SwiftUI
import UIKit

struct TestView: View {

    @State var progress: Float = 0.0

    var body: some View {
        VStack {
            Logo(animationProgress: $progress)
                .frame(width: 300, height: 300)
            Text("\(progress)")
            Slider(value: $progress)
                .padding(.horizontal)
        }
    }
}

struct Logo: UIViewRepresentable {

    @Binding var animationProgress: Float

    func makeUIView(context: Context) -> PaintCodeView {
        print("LinkLogo Make: \(animationProgress)")
        let view = PaintCodeView()
        view.progress = CGFloat(animationProgress)
        return view
    }

    func updateUIView(_ logoView: PaintCodeView, context: Context) {
        logoView.progress = CGFloat(animationProgress)
    }
}

class PaintCodeView: UIView {

    private var _progress: CGFloat = 0.0

    var progress: CGFloat {
        set {
            if newValue < 0 {
                _progress = 0
            } else if newValue > 1 {
                _progress = 1
            } else {
                _progress = newValue
            }
            setNeedsDisplay()
        }
        get {
            return _progress
        }
    }

    override func draw(_ rect: CGRect) {
        LinkStyles.drawLogoAnimated(frame: self.bounds, resizing: .aspectFit, animationProgress: _progress)
    }

}

Glitching animation

Any idea what I'm doing wrong?

RogerTheShrubber
  • 986
  • 8
  • 19
  • Hi RogerTheShrubber, I have the same issue with the black background and have reached out to PaintCode for help as I am stuck. Did you find a solution? – Pete Dec 21 '21 at 17:13

1 Answers1

1

You need to set the background color to .clear in the UIView subclass (in below example in class MyWidgetView) in order to remove the black background.

import UIKit

class MyWidgetView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        super.backgroundColor = UIColor.clear
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    override func draw(_ rect: CGRect) {
        PaintCodeClass.drawWidget(frame: self.bounds)
    }
}

struct ObstacleView: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        ObstacleUIView()
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        
    }
}
Pete
  • 213
  • 1
  • 13