backslash-f
backslash-f

Reputation: 8193

Can the changes of the ".disabled" modifier of SwiftUI be animated?

I think that the View.disabled(_:) modifier changes the .foregroundColor of a View (besides enabling / disabling interactions with it). Could the color change be animated?

I know it's pretty easy to animate say .opacity changes with implicit animations (e.g.: .animation(.default)). However the same won't work with .disabled.

Please consider the following code:

import SwiftUI

struct SomeButton: View {

    @State var isDisabled = false
    @State var isHidden = false

    var body: some View {
        VStack(spacing: 30) {
            Spacer()
            Button(action: {}) {
                Image(systemName: "pencil.circle.fill")
                    .resizable()
            }
            .frame(width: 80, height: 80)

            .disabled(isDisabled)       // 👈🏻 Will not animate at all.
            .opacity(isHidden ? 0 : 1)  // 👈🏻 Will animate just fine.
            .animation(.default)        // 👈🏻 Set to use implicit animations.

            VStack(spacing: 10) {
                Button(action: {
                    self.isHidden.toggle()
                }) {
                    Text("Hide")
                }
                Button(action: {
                    self.isDisabled.toggle()
                }) {
                    Text("Disable")
                }
            }
            Spacer()
        }
    }
}

// MARK: - Preview

#if DEBUG
struct SomeButton_Previews: PreviewProvider {
    static var previews: some View {
        SomeButton()
    }
}
#endif

This produces the following result, which presents a smooth opacity transition:

animationSample

... on the other hand the enabled / disabled color transition is binary. It doesn't look that good.

My current workaround is to change the opacity of a view based on its enabled/disabled state. So for example if a view is disabled, the opacity is 0.6. If enabled, the opacity goes back to 1.0.

But it feels wrong. There must be another way.

Upvotes: 3

Views: 1649

Answers (1)

Asperi
Asperi

Reputation: 257789

The possible solution can be to combine with .colorMultipy, of course the disabled color should be experimentally fit, but this gives common effect animatable

demo

.disabled(isDisabled)
.colorMultiply(isDisabled ?  // 👈🏻 animatable
      Color.gray /* to be selected to fit*/ : .white)
.animation(.default, value: isDisabled)

Upvotes: 3

Related Questions