newb
newb

Reputation: 212

How do I get a Color from a gradient in SwiftUI

I want to use the Color of my view to indicate a status. So if value1 = 0 the color is green, while value1 < value2 I want a gradient fading to value1 = value2 the color is red, but the view shouldn't have a gradient as a 'color', but just the one color from the gradient, that is according.

Without the gradient - no problem, but I cant figure out how to get it working, for now I've settled with a status bar, where I have an expanding mask, revealing the gradient, so at least I'm hiding the red at the beginning. Which is close, but also not what I want.

I've cut out the according code, and added a slider to change value 1 :

import SwiftUI


struct ContentView: View {

    @State private var monthTotalSpent = 100.0
    @State private var budgetdef = 1100.0


    var body: some View{
        ZStack{
            RoundedRectangle(cornerRadius: 30)
                .foregroundColor(.init(.systemGray4))
            VStack(spacing: 5){
                HStack{
                    Text("\(monthTotalSpent)")
                    Text("/")
                    Text("\(budgetdef)")
                }
                .padding(.top)
                .padding(.horizontal)
                ZStack(alignment: .center){
                    RoundedRectangle(cornerRadius: 15)
                        .foregroundColor(Color(uiColor: .systemGray6))
                        .frame(width: UIScreen.main.bounds.width-50, height: 10, alignment: .center)
                    HStack{
                        LinearGradient(colors: ((monthTotalSpent*290)/budgetdef) <= 290 ? [Color.green, Color.red] : [Color.red], startPoint: .leading, endPoint: .trailing)
                            .frame(width: UIScreen.main.bounds.width-50, height: 10, alignment: .center)
                            .mask(alignment: .leading) {
                                RoundedRectangle(cornerRadius: 4)
                                    .frame(width: ((monthTotalSpent*290)/budgetdef) < 290 ? ((monthTotalSpent*290)/budgetdef) : UIScreen.main.bounds.width-54, height: 8, alignment: .center)
                            }
                            .padding(.leading, 27)
                        Spacer(minLength: 0)
                    }
                }
                Slider(
                    value: $monthTotalSpent,
                    in: 0...1500,
                    step: 100
                )
            }
        }
    }
}

Where would I go from here? Thanks in advance!

Upvotes: 1

Views: 1181

Answers (1)

MatM
MatM

Reputation: 128

Here is a way to get a single color from a gradient by applying a percentage to RVB components.

Here is your code modified by adding the grandientColor() function that calculates the Red and Green components of the color based on the value of your Slider.

import SwiftUI

struct ContentView: View {

    @State private var monthTotalSpent = 100.0
    @State private var budgetdef = 1100.0


    var body: some View{
        ZStack{
            RoundedRectangle(cornerRadius: 30)
                .foregroundColor(.init(.systemGray4))
            VStack(spacing: 5){
                HStack{
                    Text("\(monthTotalSpent)")
                    Text("/")
                    Text("\(budgetdef)")
                }
                .padding(.top)
                .padding(.horizontal)
                ZStack(alignment: .center){
                    RoundedRectangle(cornerRadius: 15)
                        .foregroundColor(Color(uiColor: .systemGray6))
                        .frame(width: UIScreen.main.bounds.width-50, height: 10, alignment: .center)
                    HStack{
                        RoundedRectangle(cornerRadius: 4)
                            .fill(gradientColor(value: monthTotalSpent))
                            .frame(width: ((monthTotalSpent*290)/budgetdef) < 290 ? ((monthTotalSpent*290)/budgetdef) : UIScreen.main.bounds.width-54, height: 8, alignment: .center)
                            .padding(.leading, 27)
                        Spacer(minLength: 0)
                    }
                }
                Slider(
                    value: $monthTotalSpent,
                    in: 0...1500,
                    step: 100
                )
            }
        }
    }
    
    func gradientColor(value: Double) -> Color {
        let percent = value / budgetdef
        let color = UIColor(red: percent, green: 1 - percent, blue: 0, alpha: 1)
        return Color(uiColor: color)
    }
}

Upvotes: 3

Related Questions