Dynamic height custom inputView in iOS 8

I have some problems with my custom inputView for UITextFields . Depending on the text that the user must enter in the UITextField , the inputView displays only the letters you need. This means that for short texts, input with only one line of letters is sufficient, for longer texts it may take 2 or even 3 lines, so the height of the input element will be variable.

Since I expected better performance, there is only one instance of inputView that is used by each textField. Thus, the creation should happen only once, and this would simplify sometimes the necessary direct access to the InputView. InputView is set to - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField , sets the required height and will be displayed.

This works fine, but not on iOS8. There, some kind of system view containing an inputView will not update its frame so that it matches the boundaries of the input of the View when they were changed (the first time it works).

I know this can be fixed using a single instance of my inputView for textField. But I ask if there is a recommended / best way to tweak the frame or report a change in the containing view. Maybe this is an iOS8 bug that can be fixed before release?

Here is sample code to reproduce the problem:

CustomInputView

 @implementation CustomInputView + (CustomInputView*)sharedInputView{ static CustomInputView *sharedInstance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[CustomInputView alloc] init]; }); return sharedInstance; } - (id)init { self = [super init]; if (self) { self.backgroundColor = [UIColor greenColor]; } return self; } - (void)setupForTextField:(UITextField*)textField{ CGFloat height; if(textField.tag == 1){ height = 100; }else height = 50; self.frame = CGRectMake(0, 0, 320, height); } @end 

TestViewController Code

 - (void)viewDidLoad { [super viewDidLoad]; UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(15, 50, 290, 30)]; tf.text = @"bigKeyboard"; tf.inputView = [CustomInputView sharedInputView]; tf.layer.borderWidth = 1; tf.layer.borderColor = [UIColor lightGrayColor].CGColor; tf.delegate = self; tf.tag = 1; [self.view addSubview:tf]; tf = [[UITextField alloc] initWithFrame:CGRectMake(15, 100, 290, 30)]; tf.text = @"smallKeyboard"; tf.inputView = [CustomInputView sharedInputView]; tf.layer.borderWidth = 1; tf.layer.borderColor = [UIColor lightGrayColor].CGColor; tf.delegate = self; tf.tag = 2; [self.view addSubview:tf]; UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:@"dismissKeyboard" forState:UIControlStateNormal]; [button addTarget:self action:@selector(endEditing) forControlEvents:UIControlEventTouchUpInside]; button.frame = CGRectMake(15, 150, 290, 30); [self.view addSubview:button]; } - (void)endEditing{ [self.view endEditing:YES]; } - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{ [[CustomInputView sharedInputView] setupForTextField:textField]; return YES; } 
+6
source share
1 answer

I had similar problems setting up a custom keyboard from iOS 8 to iOS 10. I believe the correct solution is for the input view to provide the proper intrinsicContentSize and change (and not valid!) This value when you want to change the height of the view. Code example:

 class CustomInputView: UIInputView { var intrinsicHeight: CGFloat = 200 { didSet { self.invalidateIntrinsicContentSize() } } init() { super.init(frame: CGRect(), inputViewStyle: .keyboard) self.translatesAutoresizingMaskIntoConstraints = false } required init?(coder: NSCoder) { super.init(coder: coder) self.translatesAutoresizingMaskIntoConstraints = false } override var intrinsicContentSize: CGSize { return CGSize(width: UIViewNoIntrinsicMetric, height: self.intrinsicHeight) } } class ViewController: UIViewController { @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() textView.becomeFirstResponder() let inputView = CustomInputView() // To make the view size more clear. inputView.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0.5, alpha: 1) textView.inputView = inputView // To demonstrate a change to the view intrinsic height. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(2)) { inputView.intrinsicHeight = 400 } } } 

See also fooobar.com/questions/182300 / ....

+13
source

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


All Articles