Adjust width of UITextField to fill toolbar in landscape - ios

In a UIToolbar, I have added a UITextField to the middle of the bar (which gets added as a UIBarButtonItem) with another UIBarButtonItem (Action button) next to it. I added flexible space bar button items at the very left and very right. It looks great on portrait, but when I rotate to landscape it centers them and looks ok, but I need the text field to get stretched to fill the width and push the last button clear to the right - exactly like it does in Messages - on iPhone and iPad.
I thought Auto Layout would do the trick but Apple states you cannot create constraints for UIBarButtonItems. And indeed when I select any of the bar buttons or the text field it will not allow creating any constraints.
Could you please let me know how to accomplish this? Thanks!
EDIT: I've tried a few other combinations with fixed/flexible spaces. When I don't add any, the text field and share button are pushed over to the left:
If instead I do fixed spaces, it looks the exact same as above with 0 widths, or if I set a width then it obviously will push them over. That last space on the far right has no effect - it's not fixed against the far right side so it goes off the screen.
I tried a fixed space on the left and a flexible on the right, with the middle one fixed (or no middle one), and it looks like the screenshot above. I then changed the middle one to flexible and it turned out like this:
If I change the first to flexible, none in the middle (or if I add a fixed one), and flxed on the right, it is moved over to the right:
If the first is flexible, middle is flexible, and right is fixed, this is how it looks:
In all cases the width of the text field remains the same static value as it was originally set up in the storyboard. I think the problem is that when you set the width by dragging the frame, there are no blue guidelines to snap to so it will always remain that same width.
Did I miss any combination of spaces? If I cannot implement the desired behavior in the interface builder, how would one accomplish this in code?

To obtain a horizontally stretching text field, I had to manually set its frame in viewWillAppear and also when the orientation changes - I used viewWillTransitionToSize:withTransitionCoordinator::
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) {
self.textField.frame = CGRectMake(0, 0, self.navigationController.navigationBar.frame.size.width - self.actionButton.width - 55, self.inputTextField.frame.size.height);
} completion:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) {
}];
Previous solution (no longer works for me in latest OSes):
Add this in viewDidLoad:
self.textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;

Related

How to control layout of UIBarButtonItem controls on an iOS toolbar?

On my toolbar I am trying to properly lay out three buttons. One in the middle that should remain centered horizontally, and then one aligned left and one aligned right. But because the text for the left button is longer than either the middle button or the right one, the spacer items won't seem to produce the desired spacing effect. I've tried both fixed and flexible, but of course using the fixed type will not dynamically respond to different screen widths, and the the flexible width ones (UIBarButtonSystemItemFlexibleSpace) will not keep the middle button centered.
I've defined the layout both in Interface Builder and programmatically and I get the same effect, what you see here. For example an iPhone 6s looks like:
and an iPhone 11 Pro looks like:
As you can see the "Mid" button is not centered. By using UIBarButtonSystemItemFixedSpace instead of UIBarButtonSystemItemFlexibleSpace I could define the width of the spacers exactly, but in order to calculate it properly I would need to know the width of each UIBarButtonItem and also the right delegate method to do this in. Is this even possible, or must I do a custom view (or something else) to make this UIToolbar look like I want?
Try adding leading spaces to the Shorter title OR using the following items:
Longer-Text Button, Flexible Space, Mid Button, Flexible Space, Fixed Space, Shorter Button
The fixed space would be a hard coded value to match the width delta between the two buttons.

Autolayout not working with Custom Keyboard, is this an Apple bug, or am I missing some settings?

In a regular app, in the initial viewController, if I add two UIHorizontalStackViews, and add two buttons to each, and set their heights to be 0.5 of the view, while setting the left, top, and right properties to 0, they behave as we expect:
However, if I do this exact same process on a custom keyboard extension that uses a viewController, I get this:
You would think that it would make each UIHorizontalStackViews take 50% of the keyboard height, but no the keyboard shrinks and the buttons get smaller.
I then tried adding one single vertical stackview, that had 4 rows of horizontalstackviews, making it have height of 1.0 of it's view, and margins of left 0, top 0, right 0, in this case, the window ended up taking far more than half of the screen, more than the custom keyboard's height is allowed to be.
Not sure if this is a bug or what. I was assuming autolayout would be adjusting the keyboard height depending on screen orientation, and phone model.

Wrapping text in UITextView in Swift

UPDATE: Looks like the UITextView's width is bigger than screen's width.
It is strange since I created the UITextView using a storyboard and in preview mode it looks like it's width is less than that of the UIViewController.
I have a UITextView, in a UIViewController, that was created using storyboard.
I have similar code to populate the text in the UITextView.
self.taskGroupDescriptionTextView.text = taskGroup.description
self.taskGroupDescriptionTextView.textContainer.lineBreakMode = NSLineBreakMode.ByCharWrapping
I tried different types of lineBreakMode, break by char/word. None of them work.
My UIViewController when run on iOS simulator still has text that extends beyond the screen.
You should set constraints. Here's an example how to do it:
You click on your UITextView so that you can start editing it. At the bottom of the storyboard there are few icons and clicking on the one shown in the image will open up an editor where you can add constraints. You have plenty of options (pin to left, right, top, bottom, fix height or width, aspect ratio,... and even more if you click on a neighbour icon). Keep in mind that you have to set enough constraint so that it will be reasonable for your view controller to calculate the frame size of your view. But no worries, if you'll forget something you'll get an error.

Aligning Elements in Xcode

I seem to be having trouble aligning elements. I want this UITextField to always be center horizontally, and stay towards the top of the app.
This is what it looks like on the storyboard:
As you can see, there are constraints set - which are blue lines (I think that means they are correct)
However when I view it in the simulator:
These are the settings in the Xcode pin popup:
Question:
How do I get the UITextField to always stay center horizontally, regardless of device or orientation?
Edit 1:
I took out all constraints, I made the UILabel the full width of the view, and centered the text inside. I assumed that this would make it center, but alas not.
Storyboard:
Simulator:
Edit 2:
See the two red squares, I'm not sure how to change that text. There are no options on edit.
I also cant see how to add the other constraints that you suggested.
remove your left and right constraints and set the following one.

How to slide content over with AutoLayout

I have a messaging view where the user can select emoticons to add to the message. I have a bar above the keyboard where the user can enter their message. It looks something like this: H:|-[UIButton: emoticon]-[UITextField]-[UIButton: send]|
Now I've tried to slide all these over by setting their left constraint to constraint.constant -= screenWidth, but this didn't seem to work, as I got loads of "Could not satisfy constraints" messages in the log and none of them moved. I also had the problem of not knowing where to put the emoticons (it's a bar of UIButton with one emoji each).
Is there a way to do this in a simple way?
If I understand what you're doing right (you're sparse on the details), your problem is that your constraints are still pinned to the start and end.
You will probably need to remove the last item's right constraint before you can scroll anything.
That said, what I usually do in cases like this is wrap everything that's supposed to scroll in a plain UIView. Then I can keep their internal constraints the same, and only the UIView is pinned to the left and right of its superview. To scroll, I simply add a width constraint with the current width, remove the right constraint, and then subtract from the left constraint's constant to scroll it off screen.
That extra view gives me a guarantee that everything stays the size and location it had at the beginning of the animation, and might even allow me to optimize the animation (e.g. I can rasterize the view before I scroll it out, and UIKit then only has to move one layer).

Resources