iosswiftuisegmentedcontrol

SwiftUI Create a Custom Segmented Control also in a ScrollView


Below is my code to create a standard segmented control.

struct ContentView: View {

    @State private var favoriteColor = 0
    var colors = ["Red", "Green", "Blue"]

    var body: some View {
        VStack {
            Picker(selection: $favoriteColor, label: Text("What is your favorite color?")) {
                ForEach(0..<colors.count) { index in
                    Text(self.colors[index]).tag(index)
                }
            }.pickerStyle(SegmentedPickerStyle())

            Text("Value: \(colors[favoriteColor])")
        }
    }
}

My question is how could I modify it to have a customized segmented control where I can have the boarder rounded along with my own colors, as it was somewhat easy to do with UIKit? Has any one done this yet.

I prefect example is the Uber eats app, when you select a restaurant you can scroll to the particular portion of the menu by selecting an option in the customized segmented control.

Included are the elements I'm looking to have customized:

enter image description here

* UPDATE *

Image of the final design

enter image description here


Solution

  • Is this what you are looking for?

    enter image description here

    import SwiftUI
    
    struct CustomSegmentedPickerView: View {
      @State private var selectedIndex = 0
      private var titles = ["Round Trip", "One Way", "Multi-City"]
      private var colors = [Color.red, Color.green, Color.blue]
      @State private var frames = Array<CGRect>(repeating: .zero, count: 3)
    
      var body: some View {
        VStack {
          ZStack {
            HStack(spacing: 10) {
              ForEach(self.titles.indices, id: \.self) { index in
                Button(action: { self.selectedIndex = index }) {
                  Text(self.titles[index])
                }.padding(EdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20)).background(
                  GeometryReader { geo in
                    Color.clear.onAppear { self.setFrame(index: index, frame: geo.frame(in: .global)) }
                  }
                )
              }
            }
            .background(
              Capsule().fill(
                self.colors[self.selectedIndex].opacity(0.4))
                .frame(width: self.frames[self.selectedIndex].width,
                       height: self.frames[self.selectedIndex].height, alignment: .topLeading)
                .offset(x: self.frames[self.selectedIndex].minX - self.frames[0].minX)
              , alignment: .leading
            )
          }
          .animation(.default)
          .background(Capsule().stroke(Color.gray, lineWidth: 3))
    
          Picker(selection: self.$selectedIndex, label: Text("What is your favorite color?")) {
            ForEach(0..<self.titles.count) { index in
              Text(self.titles[index]).tag(index)
            }
          }.pickerStyle(SegmentedPickerStyle())
    
          Text("Value: \(self.titles[self.selectedIndex])")
          Spacer()
        }
      }
    
      func setFrame(index: Int, frame: CGRect) {
        self.frames[index] = frame
      }
    }
    
    
    struct CustomSegmentedPickerView_Previews: PreviewProvider {
      static var previews: some View {
        CustomSegmentedPickerView()
      }
    }