Put the UILabel / UITextField on the next line instead of out of view

I am creating a natural language form and whenever a user enters an input that is quite large, I want the whole line to move to the next line (just like a UITextView ). Right now, I get this result: http://cl.ly/image/1E1n0W28360T

This indicates two obvious problems: for one: the element that presses UITextField should go to the next line, and secondly, when canceling back, the element that was "pushed" is not "thrown" into place. In addition, UITextField should go to the next line when exiting view.bounds . Is it arbitrary to use a UITextField or a UITextView to use. It should be applicable to the situation in Figure 2.

This is a more graphical approach to what I'm trying to achieve: enter image description here

How can i solve this? And is this the right approach?

Update

Robert's answer is very good, along with some errors that he still has, there is also the problem that he is not flexible. I started refactoring the code and tried to subclass UITextField and UITextView , following Robert's approach.

When subclassing the code, there should be some delegation using UITextField to UITextView . Secondly, each part of the sentence should be divided whenever there is a UITextField between them, but I feel that it can be hardcoded in VC as well. Constraints also need to be converted to code.

Whenever I have a solution to any of these problems, I update the question and hope you get a flexible solution :)

+5
source share
1 answer

Your approach works for me.

Say you have a UITextView that displays a selectable but immutable full sentence, including the entered parameter values. And then you have an editable UITextField for each form parameter. With this setting, you can leave it a UITextView to process the text stream and use UITextViews to process the input.

In order for the UITextField appear in the text stream, the trick should hide it - or rather, reduce it to the width of its caret - and display it in the position of the last character of the parameter value.

 @interface ViewController () @property (strong, nonatomic) IBOutlet UITextView *fullTextView; @property (strong, nonatomic) IBOutlet UITextField *friendField; // Using AutoLayout constraints to position the friendField @property (strong, nonatomic) IBOutlet NSLayoutConstraint *friendFieldLeadingConstraint; @property (strong, nonatomic) IBOutlet NSLayoutConstraint *friendFieldTopConstraint; @property (strong, nonatomic) IBOutlet NSLayoutConstraint *friendFieldWidthConstraint; @property (assign, nonatomic) CGFloat initialFriendFieldWidth; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Store the intrinsic size of the friendField displaying the placeholder // (there probably a better way to this than storing the value on view load) self.initialFriendFieldWidth = self.friendField.intrinsicContentSize.width; } - (IBAction)friendFieldEditingChanged:(UITextField *)friendField { // Insert the friend name into the sentence NSString *sentencePart1 = @"I'm paying "; NSString *sentencePart2 = @"\n$ amount\nfor description"; self.fullTextView.text = [@[sentencePart1, friendField.text, sentencePart2] componentsJoinedByString:@""]; // Render the fullTextView, so that we can retrieve the friend name last character position [self.fullTextView setNeedsLayout]; [self.fullTextView layoutIfNeeded]; // Retrieve the frame of the friend name last character (in relation to the textView coordinates) UITextPosition *last = [self.fullTextView positionFromPosition:self.fullTextView.beginningOfDocument offset:sentencePart1.length + friendField.text.length]; UITextPosition *secondToLast = [self.fullTextView positionFromPosition:last offset:-1]; UITextRange *range = [self.fullTextView textRangeFromPosition:secondToLast toPosition:last]; CGRect rangeRect = [self.fullTextView firstRectForRange:range]; // Here comes the trick: // The friendField width will be reduced to the width of the caret and // placed at the last character position within the fullTextView. // This way the UITextView handles the display of the full text, // incl. the parameter values. And the UITextFields will handle the input, // while only appearing as a caret. // Retrieve the caret width CGFloat width = [self.friendField caretRectForPosition:nil].size.width; // If no text is entered, unfold friendField to reveal the placeholder if (friendField.text.length == 0) { width = self.initialFriendFieldWidth; } // Using AutoLayout constraints (see Main.storyboard) // Note: A proper implementation needs to display the caret right where it is in // relation to the input value. For now we only display it at the end of the value. self.friendFieldLeadingConstraint.constant = - rangeRect.origin.x - rangeRect.size.width; self.friendFieldTopConstraint.constant = - rangeRect.origin.y; self.friendFieldWidthConstraint.constant = width; } 

It will look as follows: (selection of text field sizes)

Natural Language Form - 1. Default view - 2. With input

Here you can download a fully working example: https://github.com/widescape/NaturalLanguageForm

+3
source

Source: https://habr.com/ru/post/1203049/


All Articles