ios – Methods to make SwiftUI Picker’s segments be truly as vast as its content material and never as vast because the widest phase?

0
29
ios – Methods to make SwiftUI Picker’s segments be truly as vast as its content material and never as vast because the widest phase?


SwiftUI does not assist this in the mean time, so that you’d must drop all the way down to UIKit, and set UISegmentedControl.apportionsSegmentWidthsByContent to true.

If you don’t need any segmented picker to have equal widths, simply use the UIAppearance APIs,

// put this in onAppear wherever you want it
UISegmentedControl.look().apportionsSegmentWidthsByContent = true

In any other case, you possibly can write your personal UIViewRepresentable. Right here is an instance:

struct FitWidthSegmenetedPicker: UIViewRepresentable {
    let choices: [Selection]
    @Binding var choice: Choice
    let titleForOption: (Choice) -> String
    
    init(
        _ choices: [Selection],
        choice: Binding,
        titleForOption: @escaping (Choice) -> String = { String(describing: $0) }
    ) {
        self.choices = choices
        self._selection = choice
        self.titleForOption = titleForOption
    }
    
    func makeUIView(context: Context) -> UISegmentedControl {
        let segmentedControl = UISegmentedControl()
        segmentedControl.apportionsSegmentWidthsByContent = true
        segmentedControl.addTarget(context.coordinator, motion: #selector(Coordinator.selectionChanged(_:)), for: .valueChanged)
        return segmentedControl
    }
    
    func updateUIView(_ uiView: UISegmentedControl, context: Context) {
        uiView.removeAllSegments()
        for possibility in choices.reversed() {
            uiView.insertSegment(withTitle: titleForOption(possibility), at: 0, animated: false)
        }
        uiView.selectedSegmentIndex = choices.firstIndex(of: choice) ?? 0
        context.coordinator.onSelectionChanged = { index in
            choice = choices[index]
        }
    }
    
    func makeCoordinator() -> Coordinator {
        .init()
    }
    
    @MainActor
    class Coordinator: NSObject {
        var onSelectionChanged: ((Int) -> Void)?
        
        @objc func selectionChanged(_ sender: UISegmentedControl) {
            onSelectionChanged?(sender.selectedSegmentIndex)
        }
    }
}

Utilization:

struct ContentView: View {
    let choices = ["x", "xx", "xxx", "xxxx", "xxxxxxxxxxxx"]
    @State personal var choice = "x"
    
    var physique: some View {
        FitWidthSegmenetedPicker(choices, choice: $choice)
            .fixedSize()
        Textual content(choice)
    }
}

enter image description here

LEAVE A REPLY

Please enter your comment!
Please enter your name here