GroupBox not animating on picker's selection change

49 Views Asked by At

I have a picker view inside a groupbox. When changing the selected value inside the picker the size of the picker's label changes and the groupbox's width too. I added an animation on the groupbox with the picker's selection value as a value to monitor for changes. But the groupbox does not animate

GroupBox {
             
                    Picker("Period", selection: $periodIndex) {
                        ForEach(0..<periods.count, id: \.self) { index in
                            Text(periods[index]).tag(index)
                        }
                    }
                    .tint(.white)   
       
        }
        .animation(.spring, value: periodIndex)

Since I never animated using an integer I used a boolean that toggles when the picker's selection value changes but it didn't work too

1

There are 1 best solutions below

7
Benzy Neez On

I don't think the lack of animation has anything to do with the GroupBox. This is just the way a native Picker works when the picker style is .menu. But you notice it a bit more here because the GroupBox adds a background shape which is changing in size when the selection changes.

I couldn't find a way to animate the change. But you can at least avoid a change of group size by applying a minWidth to the Picker. Something like:

Picker("Period", selection: $periodIndex) {
    // content as before
}
.frame(minWidth: 100)

The selection itself still changes without animation, but at least the GroupBox does not change size.

Ps. you can edit your own post to fix the erroneous value on the .animation modifier.


EDIT I tried it with the string array you gave in a comment. A minWidth of 110 stops the size from changing for me and I don't see any wrapping issue.

private let periods = ["Fajr", "Sunrise", "Dhuhr", "Asr", "Maghrib", "Isha", "Midnight"]
@State private var periodIndex = 0

var body: some View {
    GroupBox {
        Picker("Period", selection: $periodIndex) {
            ForEach(0..<periods.count, id: \.self) { index in
                Text(periods[index])
                    .tag(index)
            }
        }
        .tint(.white)
        .frame(minWidth: 110)
    }
}

Animation