Erratic input textfield positioning in Chat SDK v2 in SwiftUI | Community
Skip to main content

Erratic input textfield positioning in Chat SDK v2 in SwiftUI

  • February 17, 2022
  • 0 replies
  • 0 views

The following code demonstrates erratic positioning of the text input field in the Chat UI in a simple SwiftUI project. Textfield jumps to near top of view on first tap when keyboard is presented. Other gestures can cause the textfield to reposition to just atop the keyboard as expected, but repositions to near top of view with next presentation of keyboard. This is seen on simulator and device, iOS 14, 15+.

My guess is that the iOS system is automatically adding padding under the textfield when the keyboard is presented and the SDK is also adding the padding manually.

Create a SwiftUI Xcode project and add SPM package dependencies:

- ZendeskChatSDK 2.0.0 - Next Major

- ZendeskSupportSDK 5.0.0 - Next Major

Replace the ContentView.swift code with the following:

import ChatSDK

import ChatProvidersSDK

import CommonUISDK

import MessagingSDK

import SwiftUI

import ZendeskCoreSDK

 

struct ContentView: View {

    @State var showSupportChat: Bool = false

    

    var body: some View {

        VStack {

            HStack {

                Spacer()

                Button(action: {

                    showSupportChat = true

                }, label: {

                    Image(systemName: "questionmark.circle")

                        .resizable()

                        .frame(width: 24, height: 24)

                })

                    .padding(.trailing)

            }

            .padding(.top, 16)

            Spacer()

            Text("Main Page").font(.largeTitle)

            Spacer()

        }

//      same result with both following presentation methods        

        .sheet(isPresented: $showSupportChat, onDismiss: {

//        .fullScreenCover(isPresented: $showSupportChat, onDismiss: {

            showSupportChat = false

        }, content: {

            MessagingView()

                .accentColor(.white)

        })

        .accentColor(.red)

    }

}

 

// https://developer.zendesk.com/documentation/classic-web-widget-sdks/unified-sdk/ios/swiftui-integration/

struct MessagingView: UIViewControllerRepresentable {

    @Environment(\.presentationMode) var presentationMode

    

    func makeUIViewController(context: Context) -> UIViewController {

        Zendesk.initialize(

            appId: "APP_ID",

            clientId: "MOBILE_SDK_CLIENT",

            zendeskUrl: "https://my-app-id.zendesk.com"

        )

 

        let visitorInfo = VisitorInfo(

            name: "Anon E. Moose",

            email: "moose.on.loose@somewhere.com",

            phoneNumber: "+1(555)555-1212"

        )

        

        Zendesk.instance?.setIdentity(

            Identity.createAnonymous(

                name: visitorInfo.name,

                email: visitorInfo.email

            )

        )

        

        Chat.initialize(accountKey: "CHAT_ACCOUNT_KEY")

        let chatConfig = self.chatAPIConfig(

            info: visitorInfo,

            tags: ["app_name", "en", "US"])

        Chat.instance?.configuration = chatConfig

 

        // https://developer.zendesk.com/documentation/classic-web-widget-sdks/unified-sdk/ios/customizing_the_look/

        CommonTheme.currentTheme.primaryColor = .red

        

        var chatVC = UIViewController()

        do {

            let chatEngine = try ChatEngine.engine()

            chatVC = try Messaging.instance.buildUI(

                engines: [chatEngine],

                configs: [self.messagingConfig(), self.chatConfig()]

            )

        }

        catch {

            print("Error creating Chat view controller: \(error)")

        }

 

        let button = UIBarButtonItem(image: nil, style: .plain, target: nil, action: nil)

        button.primaryAction = UIAction(

            image: UIImage(systemName: "xmark.circle")

        ) {_ in

            presentationMode.wrappedValue.dismiss()            

        }

 

        chatVC.navigationItem.leftBarButtonItem = button

 

        // CommonTheme.currentTheme.primaryColor = .red does not affect Navbar color

        // as per documentation (link above). Let's try and force it.

        let appearance = UINavigationBarAppearance()

        appearance.configureWithOpaqueBackground()

        appearance.backgroundColor = .red

        

        let attrs: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white]

        appearance.titleTextAttributes = attrs

        appearance.largeTitleTextAttributes = attrs

        

        UINavigationBar.appearance().standardAppearance = appearance

        UINavigationBar.appearance().scrollEdgeAppearance = appearance

        chatVC.navigationController?.navigationBar.standardAppearance = appearance

        chatVC.navigationController?.navigationBar.scrollEdgeAppearance = appearance

 

        return UINavigationController(rootViewController: chatVC)

    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {

        //...

    }

    func chatAPIConfig(info: VisitorInfo, tags: [String]) -> ChatAPIConfiguration {

        let chatAPIConfig = ChatAPIConfiguration()

        chatAPIConfig.tags = tags

        chatAPIConfig.visitorInfo = info

        return chatAPIConfig

    }

    func messagingConfig() -> MessagingConfiguration {

        let messagingConfig = MessagingConfiguration()

        messagingConfig.name = "My App"

        return messagingConfig

    }

    func chatConfig() -> ChatConfiguration {

        let chatConfig = ChatConfiguration()

        let formConfig = ChatFormConfiguration(

            name: .required,

            email: .optional,

            phoneNumber: .hidden,

            department: .hidden

        )

        chatConfig.preChatFormConfiguration = formConfig

        chatConfig.isPreChatFormEnabled = true

        chatConfig.isOfflineFormEnabled = true

        chatConfig.isChatTranscriptPromptEnabled = false

        chatConfig.isAgentAvailabilityEnabled = true

        chatConfig.chatMenuActions = [.endChat]

        return chatConfig

    }

}

struct ContentView_Previews: PreviewProvider {

    static var previews: some View {

        ContentView()

    }

}