2

How can I change 2 different colors of an SVG in code in Swift? The SVG icon consists of an arrow and a circle. I would like to set color of an arrow separately from the color of a circle. Can I do that in Swift?

By using this code I would set the tint color of the wheole icon to blue.

let palyImage = UIIImage(name: "play").withRenderingMode(.alwaysTemplate)
playImageView.image = playImage
playImageView.tintColor = .systemBlue

How can I apply another color to the same icon so the icon is in 2 different colors?

I did not manage to google any advice on how I can change two different colors inside same SVG. So how can I add another color to the SVG icon? Is it even possible Also is there any special way the SVG should be made (layers or something)? Are there some special layers that designer needs to insert inside SVG? I never created SVG myself...

SimpleApp
  • 506
  • 4
  • 17
  • Maybe try out SF symbols in iOS 15: https://stackoverflow.com/a/68697066/14351818 – aheze Aug 08 '21 at 20:12
  • Thanks, I watched WWDC 21 regarding the SFSymbols but as I understood you can create an SVG icon containing 2 colors but you cannot change colors of it during runtime. When you close colors they are set. Or at leats I failed to understand how to change them from the code. Also multicolour symbols are only supported in iOS 15 :( – SimpleApp Aug 08 '21 at 20:17
  • You can change it at runtime! I showed how in my answer. But yeah, it's iOS 15+... – aheze Aug 08 '21 at 20:18
  • You already asked the same question several days ago, didn't you? What's stopping you from editing the original question? – El Tomato Aug 08 '21 at 20:46
  • I did edit the question but it remained closed so no-one was able to answer it. So I deleted the old one and opened a new one. – SimpleApp Aug 11 '21 at 14:50

1 Answers1

0

Check out this library Snowflake, it renders SVG as UIView.

All paths in the SVG file will be rendered as a single CALayer, and they can be accessed later in UIView().layer.sublayers.

And colors can be applied to the corresponding layer matching the index order found in SVG source code.

func load() {
    guard let path = Bundle.main.path(forResource: "fileName", ofType: "svg"),
          let data = try? Data(contentsOf: URL(fileURLWithPath: path)),
          let document = Document(data: data)
    else { return }
    // load SVG to a UIView
    svgView = document.svg.view(size: CGSize(width: 300, height: 300))
    // change path color
    (svgView.layer.sublayers as? [CAShapeLayer])?.enumerated().forEach { index, layer in
        layer.fillColor = index % 2 == 0 ? UIColor.green.cgColor : UIColor.red.cgColor
    }
    
    self.view.addSubview(svgView)
}

For example,

In the repo's example project, there is an image named "shape_pencils.svg", which has preset color as the left one showing.

enter image description here Then it can be changed to the right one by the following code.


    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        (svgView.layer.sublayers as? [CAShapeLayer])?.enumerated().forEach { index, layer in
            layer.fillColor = index % 2 == 0 ? UIColor.green.cgColor : UIColor.red.cgColor
        }
        
    }

Here is how it works. For every SVG file, if you open it in a text editor, you will see the source code like the following snapshot showing the "shape_pencils". It contains 19 paths and lines, each one of which will be rendered as a corresponding CALayer.

enter code here

Then you can match your arrow and circle by the index order found in the source code. enter image description here

Other popular libraries might also works since they use UIView and its CALayer as well

JsW
  • 1,682
  • 3
  • 22
  • 34