V8tr / KeyboardAvoidanceSwiftUI

How to move SwiftUI view up when keyboard appears https://www.vadimbulavin.com/how-to-move-swiftui-view-when-keyboard-covers-text-field/
https://www.vadimbulavin.com
The Unlicense
325 stars 36 forks source link

ViewModifier increases height of view on load. #4

Open sethi-ishmeet opened 4 years ago

sethi-ishmeet commented 4 years ago

I applied the View Modifier on a HStack that includes a TextField and a Button. Although the keyboard adaptivity works fine, the initial height has increased and my content has been centred automatically.

            HStack(alignment: .bottom) {
                TextField("Write a Comment", text: $newComment)
                    .padding(.all, 10)
                    .font(.system(size: 12))
                    .background(Color.gray.opacity(0.1))
                    .cornerRadius(10)
                Button(action: {
                    print(self.newComment)
                }) {
                    Image(systemName: "paperplane.fill")
                        .font(.system(size: 20))
                }
                .disabled(newComment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
            }
        .keyboardAdaptive()
            .padding(.all, 10)

Screen Shot 2020-04-23 at 11 32 13 PM

sethi-ishmeet commented 4 years ago

The above code is encapsulated in a VStack which also has a list above this HStack. Applying the ViewModifier on the Top Level View works perfectly. Why's that?

Also, Is there a way to account for the height of TabBarView in this? As My app is based on Tab View, the field goes higher than expected because of tab view.

Coffeemate commented 4 years ago

@sethi-ishmeet When you apply the modifier to the HStack it actually wraps your HStack in a GeometryReader. GeometryReader always tries to fill all available space, and it centers its content (your HStack) – that's why your view has increased in size.

gorkaertzilla commented 4 years ago

@Coffeemate What would be the alternative? Pass the frameSize to the keyboardAdaptive?

sethi-ishmeet commented 4 years ago

@ercillagorka I observed that when you apply this ViewModifier to the parent view, it works as expected. However, I think that it should be applied to specific text field and not the whole view.

V8tr commented 4 years ago

@Coffeemate many thanks for your explanation. I've added a note to the article based on your comment.

sethi-ishmeet commented 4 years ago

@V8tr Thanks for updating the article. It might also be worth mentioning that the View Modifier should be applied to the parent view vs. the Text Field or child view. For example, I changed where I was applying the View Modifier which fixed the issue. Below is the working code:


var body: some View {
    VStack {
            PagedList(viewModel: comments, id: \.id) { comment in
                CommentBubble(comment: comment)
                ForEach(comment.replies, id: \.id) { reply in
                    CommentBubble(comment: reply)
                        .padding(.leading, 20)
                }
            }

            HStack {
                TextField("Write a Comment", text: $newComment)
                    .padding(.all, 10)
                    .font(.system(size: 12))
                    .background(Color.gray.opacity(0.1))
                    .cornerRadius(10)
                    .disabled(self.comments.addCommentStatus == .loading)

                if self.comments.addCommentStatus == .loading {
                    Spinner()
                        .frame(width: 20, height: 20, alignment: .leading)
                } else {
                    Button(action: {
                        self.comments.addComment(self.newComment) { _ in
                            self.newComment = ""
                        }
                    }) {
                        Image(systemName: "paperplane.fill")
                            .font(.system(size: 20))
                    }
                    .disabled(newComment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
                } 
                //.keyboardAdaptive() <-- applying view modifier here breaks the view like in above screenshot. However, when we apply it to the parent View as applied in this code, it works perfectly fine.

            }
            .padding(.all, 10)
        }
        .keyboardAdaptive() // <-- This works as expected
}
GrandSteph commented 4 years ago

@V8tr Loved the article. Well written and allowed me to understand all. I'm still a beginner and really can appreciate when subtle things are explained well.

If the texfield is buried down the view Hierarchy it messes the geometry.frame(in: .global) as it doesn't seem to return the top level but the parent one.

saroar commented 3 years ago

I don't know why my iPhone 6s alway look like this OverLap IMG_9551