0

Swift 5, Xcode 10

The layout of my UIViewController:

enter image description here

I use this code to push the Server Text Field up when the keyboard is opened.

At first it pushed the bottom UIStackView into the top one, so I added the Server Stack View.top >= Username Stack View.bottom + 20 constraint and now it's keeping a proper distance.

BUT now it also automatically decreases the height of the Server Text Field when it's pushed up. Giving the Server Stack View a fixed height of 60.5 smushes the "Login" button, so I set the height of the Username Stack View to a fixed 110.5, which didn't change anything.

I tried changing the Vertical Content Compression Resistance Priority of multiple UI elements to 999 but there's always one UI element whose height is decreased.

As you can see in this screenshot, there's enough space above the keyboard:

enter image description here

How can I make auto layout use this space instead of "smushing" UI elements?

Edit:

I found out what this additional space is: It's the height of the "version" label and its constraint (30pts to the bottom of the screen in my case). Unfortunately I haven't been able to get rid of this yet - apart from removing the label, which still doesn't stop the "smushing".

Neph
  • 1,823
  • 2
  • 31
  • 69
  • What does it mean `smushing`? – Andrew Jul 01 '19 at 10:55
  • @Andrew [Definition](https://www.dictionary.com/browse/smush). ;) Look at the textfield below the "Server" label and compare it to the other one - that's what happens. Depending on what I set the spacing between the "Login" button and the "Server" label to, the textfield can even end up as a thing line. – Neph Jul 01 '19 at 11:25
  • It is little bit unclear what you asking... Usual way to work with keyboard is using `UIScrollView` and increase content offset of it on keyboard pop up. – Andrew Jul 01 '19 at 11:31
  • A ScrollView is only useful if there are a lot of elements that are spaced starting from the same point. My "Server" TextField is supposed to be at the bottom of the page, which adds a lot of empty space between it and the "login" button, which would still exist in the ScrollView. Instead I want to use this space to display the "Server" TextField when needed. My question stays the same: How do I decrease the fixed space between the keyboard and the "Server" TextTield, so that said TextField can be displayed using its full height (30pts) instead of being "smushed" as schown in the screenshot. – Neph Jul 01 '19 at 11:50
  • Which constraint do you change on `Keyboard Pop Up`? Your `Server` text field would be on bottom only on iPhone 6 or 5, on Xs Max it would be in center. It is strange what you offset you server stack view from center, but not from bottom of safe layout. – Andrew Jul 01 '19 at 11:58
  • I don't change anything, I'm using a swift file I download from Github, check the link I posted. `on Xs Max it would be in center` - No, it's still on the bottom. Look at the constraints in the first screenshot: For the "Version" label and the "Server Stack View" I go bottom-up, while for the "Username Stack View" I go up from the middle. Please read my question, all this information is already there. – Neph Jul 01 '19 at 12:05
  • How can you use file which related to Spring animation framework to update your UI? If you don't change anything, why constraints are changed? – Andrew Jul 01 '19 at 12:12
  • I added the file to my project, then simply changed the type of the constraint between the "Server" TextField and the "Version" label to `KeyboardLayoutConstraint`(as described [here](https://stackoverflow.com/a/35468229/2016165)). – Neph Jul 01 '19 at 12:18
  • I think you should not use code from this file. Your situation is simple, you just need to listen for event `Keyboard Show` and then just change bottom constraint from `Server Stack View` or constraint between `Server Stack View` and `User Name Stack View`. Code from file you mention resizing your view what can cause a "smushing" – Andrew Jul 01 '19 at 12:23
  • `I think you should not use code from this file.` - Why? The code I linked to adds an observer for `keyboardWillShowNotification`, there's no point in re-inventing the wheel if there's already existing, working code. Plus, I already set the constraint between the two StackViews - look at the screenshot I posted and read the explanation. I just want to tweak it, so it doesn't add the additional space but instead uses it to display the TextFields properly. – Neph Jul 01 '19 at 12:31
  • @Andrew Do you know how to fix the problem? – Neph Jul 01 '19 at 13:44
  • Yes, you can share your example project with me, and I will fix it. – Andrew Jul 01 '19 at 13:46
  • Sorry, I've not got an example project, just my main one, which I can't share. Could you please post it as an answer, so others, who come across the same problem, are able to see and fix it too. – Neph Jul 01 '19 at 13:50
  • You see, it is a little bit complicated, I think the only way to fix your problem it is to change constraint of` Server Stack View` when Keyboard Shows Up, I do not understand why do you persist against this – Andrew Jul 01 '19 at 13:54
  • Please just read my question, I keep having to repeat everything I've already written. This constraint is being changed (look at the code I linked to), which works properly, so there's no need to change that because it isn't a problem! If you know how to fix the actual problem (again, look at my question), please post an answer or describe your solution here in the comments and I'll test it. – Neph Jul 01 '19 at 13:59
  • @Andrew So, do you know how to fix the actual problem and are you willing to explain how? – Neph Jul 02 '19 at 08:49
  • I found out what this additional space is: It's the height of the "version" label and its constraint (30pts to the bottom of the screen in my case). Unfortunately I haven't been able to get rid of this yet - apart from removing the label, which still doesn't stop the "smushing". – Neph Jul 08 '19 at 13:21

1 Answers1

0

The additional empty space above the keyboard equals to the height of the "version" label and its constraint (30pts to the bottom of the screen in my case).

The "squishing" is somehow caused by the centerY - 120 constraint of the UIStackView and even changing the "Content Compression Resistance Priority" didn't work. Plus, if there's a surrounding UIScrollView, it complains about a missing constraint for the "y position" (even if the other constraints are set properly).

Unfortunately the only fix I've found so far that works for both problems is to remove the cause and change the layout. :/

What I ended up with:

enter image description here

A few things worth noting:

  • The Child View was added to always keep the "version" label at the bottom of the screen - even when the keyboard is active.
  • The Login View uses the KeyboardLayoutConstraint class for its "bottom" constraint. Without it the scrolling would be completely disabled.
  • The size of the Stack View is set through the labels and text fields inside.
  • The two extra UIStackView and UIViews (1x username, 1x server) had to be added to maintain a width of 200 for the UITextFields but still have the surrounding UIStackView and UIScrollView use leading/trailing constraints of 0pts. Without, positioning everything horizontally didn't stick, Xcode complained and the UIScrollView was pretty narrow, which also meant that it wasn't possible to scroll on the sides.
  • The "top + 100" constraint (Stack View) is visible even when the keyboard is up and the UIScrollView is scrollable. I'm aware it's not pretty but it's the only solution I've found that doesn't stick the text fields to the top of the view, since "middle - 100" doesn't work. It's probably possible to get rid of it by changing the KeyboardLayoutConstraint class.
Neph
  • 1,823
  • 2
  • 31
  • 69