Home > other >  Aligning controls better for Better ui design look and feel understanding of stacks
Aligning controls better for Better ui design look and feel understanding of stacks

Time:06-12

I am trying to get my controls in a. nice boarded box but I can't seem to fit them it could be my circle size in my progressive but could be just my understanding of my stacks, I am just new to swift ui after using .net C sharp for many years.

This is my main view

import SwiftUI

struct CaloriesView: View {
var body: some View {
    ZStack  {
        ProgressRingView()
    }
    
    ZStack{

        Label("Base Goals", systemImage: "folder.circle").font(.system(size: 30))
    }
    
    HStack{
        
        Label("Daily Limit", systemImage: "flag.fill").font(.system(size: 30))
        
        Label("Food", systemImage: "fork.knife").font(.system(size: 30))
    }
    HStack{
        Label("Exercise Taken", systemImage: "flag.fill").font(.system(size: 30))
    }
}
}

struct CaloriesView_Previews: PreviewProvider {
  static var previews: some View {
     CaloriesView()
 }
}

But what am looking moreis the progress ring to the left and the icons properly aligned to the right

enter image description here

This is my circle how I create it in my progress view

Import SwiftUI 
struct ProgressRingView: View {
@State var progress = 0.0
let colors: [Color] = [.yellow, .red,.blue, .purple]

var body: some View {
        ZStack{
            // MARK:Place Holder Ring
            Circle()
                .stroke(lineWidth: 20)
                .foregroundColor(.gray)
                .opacity(0.1)
            
            // MARK: Colored Ring
            Circle()
                .trim(from: 0.0, to: min(progress,1.0))
                .stroke(  AngularGradient(gradient: Gradient(colors: colors), center: .center,startAngle: .degrees(0), endAngle: .degrees(360   45)) ,style: StrokeStyle(lineWidth: 15, lineCap: .round, lineJoin: .round))
                .rotationEffect((Angle(degrees: 270)))
                .animation(.easeInOut(duration: 1.0),value:progress)
                .onAppear{
                    progress=1
                }
            
            VStack(spacing:30)
            {
                //MARK : Elapsed Time
                
                VStack(spacing:5)
                {
                    Text("Calories")
                        .opacity(0.7)
                }
                .padding(.top)
                
                //MARK :Remiaing Time
                
                VStack(spacing:5)
                {
                    Text("Rmaining ")
                        .opacity(0.7)
                    
                    Text("0:00")
                        .font(.title2)
                        .fontWeight(.bold)
                }
            }
        }
        .frame(width: 250, height: 250)
        .padding()
                        }
                        }
                        
            struct ProgressRingView_Previews: PreviewProvider {
    static var previews: some View {
        ProgressRingView()
    }
}

Edit

To show the style of what am looking for its kinda like my fitness pal but not exactly the same.

enter image description here

CodePudding user response:

Use a combination of HStack and a nested VStack to achieve a similar layout:

struct CaloriesView: View {
    var body: some View {
        HStack {
            ProgressRingView()
            VStack(alignment: .leading) {
                Label("Base Goals", systemImage: "folder.circle")
                Label("Daily Limit", systemImage: "flag.fill")
                Label("Food", systemImage: "fork.knife")
                Label("Exercise Taken", systemImage: "flag.fill")
            }
        }
            .padding()
    }
}

This is how the result looks like on an iPhone 13 simulator: Screenshot of a modified progress screen

To make it look nicer, I also took the liberty of fixing a typo, removing a fixed font size of 30 from the labels and shrinking the frame of the ProgressRingView down to 150x150.

Note that in your original code you're using ZStacks and HStacks with just a single view inside them: that doesn't make much sense because the stack are supposed to lay out several items and they aren't useful for just a single item.

Now, on my screenshot you may notice that the texts of the labels aren't quite aligned, but I'd suggest to do it as a separate exercise because we're all here to learn. Happy SwiftUIing!

CodePudding user response:

I created a little playground app on the iPad to show how you might approach creating this view.

It's not perfect but hopefully will give you some pointers.

I've extracted a couple of the views into reusable components for you and added the title etc...

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(alignment: .center) {
            VStack(alignment: .leading) {
                Text("Calories")
                    .font(.system(.largeTitle))
                
                Text("Remaining = Goal - Food   Exercise")
            }
            
            DataView()
        }
        .padding()
        .background(Color.init(white: 0.05))
        .cornerRadius(16)
        .shadow(color: .black, radius: 5, x: 0, y: 0)
    }
}

struct DataView: View {
    var body: some View {
        HStack(spacing: 50) {
            CircleView()
            
            VStack(alignment: .leading) {
                TagView(
                    image: .init(systemName: "flag.fill"), 
                    color: .gray,
                    title: "Base Goal",
                    number: 2300
                )
                
                TagView(
                    image: .init(systemName: "fork.knife"),
                    color: .blue,
                    title: "Food",
                    number: 0
                )
                
                TagView(
                    image: .init(systemName: "flame.fill"),
                    color: .orange,
                    title: "Exercise",
                    number: 0
                )
            }
        }
    }
}

struct TagView: View {
    let image: Image
    let color: Color
    let title: String
    let number: Int
    
    var body: some View {
        HStack {
            image
                .resizable()
                .aspectRatio(contentMode: .fit)
                .foregroundColor(color)
                .frame(width: 20, height: 30, alignment: .center)
            
            VStack(alignment: .leading) {
                Text(title)
                    .font(.system(.subheadline))
                Text("\(number)")
                    .font(.system(.headline))
            }
        }
    }
}

struct CircleView: View {
    var body: some View {
        ZStack {
            Circle()
                .stroke(
                    AngularGradient(colors: [.red, .green, .blue, .red], center: .init(x: 0.5, y: 0.5)),
                    lineWidth: 5
                )
                .frame(width: 100, height: 100, alignment: .center)
            
            VStack(alignment: .center) { 
                Text("2300")
                    .font(.system(.title))
                
                Text("Remaining")
                    .font(.system(.caption))
            }
        }
    }
}

It looks like this... enter image description here

  • Related