Search code examples
iosswiftuitextfieldsecurefield

SwiftUI - Detect taps in a disabled SecureField?


I am writing an iOS app using SwiftUI. As part of the data presented, I need to have a password field with a show/hide button that toggles between hidden/visible. To do this, I'm using a combination of SwiftUI's SecureField and TextField controls. Both are in the disabled state to prevent users from editing, as I want this field to be read-only. This setup is working perfectly. (See screenshot below)

enter image description here

Now I would like to add functionality that would allow the user to copy the password to the clipboard just by tapping on it. I've added an onTapGesture block to my SecureField, however it is never called. I believe this is due to the fact that my SecureField/TextField is marked as disabled. A snippet of my code follows:

        ZStack(alignment: .trailing) {
            if isSecured {
                VStack {
                    SecureField("", text: Binding.constant(text))
                        .disabled(true)
                        .onTapGesture {
                            print("USER TAPPED!")
                        }
                }
            } else {
                TextField("", text: Binding.constant(text))
                    .disabled(true)
            }
            
            Image(systemName: self.isSecured ? "eye" : "eye.slash")
                .accentColor(.gray)
                .foregroundColor(.gray)
                .frame(width: 20, height: 20, alignment: .center)
                .modifier(TouchDownUpEventModifier(changeState: { (buttonState) in
                    
                    withAnimation {
                        self.isSecured.toggle()
                    }
                }))
        }

Is there a way to accomplish this? I want my SecureField/TextField to be read-only but still detect when a user taps the control?


Solution

  • I was able to solve this by adding the following modifiers on my ZStack:

    .contentShape(Rectangle())
    .onTapGesture {
       ...
    }
    

    Once I did this, my ZStack began intercepting the touch events and I could perform the desired action.