简体   繁体   中英

SwiftUI - UIViewRepresentable glitching when wrapping UIView with custom drawing

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)
    }

}

正确的动画

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)
    }

}

毛刺动画

Any idea what I'm doing wrong?

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) {
        
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM