Home > Net >  SwiftUI: can toolbarBackground modifier take a custom color?
SwiftUI: can toolbarBackground modifier take a custom color?

Time:10-22

I am trying to use iOS 16's toolbarBackground modifier. The example gives the following usage:

  .toolbarBackground(
      Color.blue,
      for: .tabBar
  )

That works as expected. I have a Color extension that I am using throughout my app that allows it take hex codes:

Color extension

 extension Color {
  init?(_ hex: String) {
    var str = hex
    if str.hasPrefix("#") {
      str.removeFirst()
    }
    if str.count == 3 {
      str = String(repeating: str[str.startIndex], count: 2)
          String(repeating: str[str.index(str.startIndex, offsetBy: 1)], count: 2)
          String(repeating: str[str.index(str.startIndex, offsetBy: 2)], count: 2)
    } else if !str.count.isMultiple(of: 2) || str.count > 8 {
      return nil
    }
    let scanner = Scanner(string: str)
    var color: UInt64 = 0
    scanner.scanHexInt64(&color)
    if str.count == 2 {
      let gray = Double(Int(color) & 0xFF) / 255
      self.init(.sRGB, red: gray, green: gray, blue: gray, opacity: 1)
    } else if str.count == 4 {
      let gray = Double(Int(color >> 8) & 0x00FF) / 255
      let alpha = Double(Int(color) & 0x00FF) / 255
      self.init(.sRGB, red: gray, green: gray, blue: gray, opacity: alpha)
    } else if str.count == 6 {
      let red = Double(Int(color >> 16) & 0x0000FF) / 255
      let green = Double(Int(color >> 8) & 0x0000FF) / 255
      let blue = Double(Int(color) & 0x0000FF) / 255
      self.init(.sRGB, red: red, green: green, blue: blue, opacity: 1)
    } else if str.count == 8 {
      let red = Double(Int(color >> 24) & 0x000000FF) / 255
      let green = Double(Int(color >> 16) & 0x000000FF) / 255
      let blue = Double(Int(color >> 8) & 0x000000FF) / 255
      let alpha = Double(Int(color) & 0x000000FF) / 255
      self.init(.sRGB, red: red, green: green, blue: blue, opacity: alpha)
    } else {
      return nil
    }
  }
}

I am trying to use it within the toolbarBackground modifier like:

 .toolbarBackground(
      Color("##00FF00"),
      for: .tabBar
  )

and it's not working. Is the API still limited to where it can only use basic colors?

CodePudding user response:

It is not the toolbarBackground modifier that is not working, I suspect that it is your Color init?(_ hex: String) {...} function that is not working.

Try this code example and code to convert hex to Color. Works well for me, including for the toolbarBackground.

So to answer the question, no the API is not limited to where it can only use basic colors.

struct ContentView: View {
    var body: some View {
        TabView {
            NavigationView {
                List(0..<3, id: \.self) { i in
                    Text("item-\(i)").foregroundColor(Color(hex: "#0078d4"))
                }
                .navigationBarTitle("bar title")
                .toolbarBackground(Color(hex: "#00FF00"), for: .tabBar)
                .background(Color(hex: "#e2c9ed"))
            }
        }
    }
}


extension Color {

    init(hex: String) {
        let trimHex = hex.trimmingCharacters(in: .whitespacesAndNewlines)
        let dropHash = String(trimHex.dropFirst()).trimmingCharacters(in: .whitespacesAndNewlines)
        let hexString = trimHex.starts(with: "#") ? dropHash : trimHex
        let ui64 = UInt64(hexString, radix: 16)
        let value = ui64 != nil ? Int(ui64!) : 0
        // #RRGGBB
        var components = (
            R: CGFloat((value >> 16) & 0xff) / 255,
            G: CGFloat((value >> 08) & 0xff) / 255,
            B: CGFloat((value >> 00) & 0xff) / 255,
            a: CGFloat(1)
        )
        if String(hexString).count == 8 {
            // #RRGGBBAA
            components = (
                R: CGFloat((value >> 24) & 0xff) / 255,
                G: CGFloat((value >> 16) & 0xff) / 255,
                B: CGFloat((value >> 08) & 0xff) / 255,
                a: CGFloat((value >> 00) & 0xff) / 255
            )
        }
        self.init(.sRGB, red: components.R, green: components.G, blue: components.B, opacity: components.a)
    }

}
  • Related