2013-08-15 13 views

Odpowiedz

1

Hacky rozwiązaniem tego problemu byłoby mieć UITextField w widoku, ale ukryte, a następnie wywołać na nim [textfield staćFirstResponder].

Właśnie testowałem to i to działa

UITextField * randofield = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; 
[self.view addSubview:randofield]; 
// doesn't have to be hidden... but to be safe. 
randofield.hidden = YES; 
[randofield becomeFirstResponder]; 

Trzeba mieć to być subview uważa inaczej to nie zadziała.

5

Innym rozwiązaniem jest dodanie tych metod do realizacji UIViewController:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self reloadInputViews]; 
} 

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 

- (UIView *)inputAccessoryView { 
    if (!_textField) { 
     _textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; 
     _textField.backgroundColor = [UIColor whiteColor]; 
     _textField.delegate = self; 
    } 
    return _textField; 
} 

#pragma mark - UITextFieldDelegate 

- (BOOL)textFieldShouldReturn:(UITextField *)textField { 
    [textField resignFirstResponder]; 
    return YES; 
} 

i dodać zmienną _textField do interfejsu:

@interface ViewController : UIViewController <UITextFieldDelegate> { 
    UITextField *_textField; 
} 
@end 
9

Nie można przywołać klawiaturę bez obiektu, który może stać się pierwszy ratownik. Istnieją dwa sposoby obejścia:

  • Podklasa UIView i wdrożenie protokołu UIKeyInput w nim. Na przykład:

    W swoim pliku .h:

    @interface InputObject : UIView<UIKeyInput> 
    @property (nonatomic, copy) NSString *text; 
    @property (nonatomic, strong) UIView *inputAccessoryView; // You must override inputAccessoryView , since it's readonly by default 
    @end 
    

    w pliku .m, wdrożenia protokołu:

    - (BOOL)canBecomeFirstResponder 
    { 
        return YES; 
    } 
    
    - (BOOL)hasText 
    { 
        return [self.text length]; 
    } 
    
    - (void)insertText:(NSString *)text 
    { 
        NSString *selfText = self.text ? self.text : @""; 
        self.text = [selfText stringByAppendingString:text]; 
        [[NSNotificationCenter defaultCenter] postNotificationName:kInputObjectTextDidChangeNotification object:self]; 
    } 
    
    - (void)deleteBackward 
    { 
        if ([self.text length] > 0) 
         self.text = [self.text substringToIndex:([self.text length] - 1)]; 
        else 
         self.text = nil; 
        [[NSNotificationCenter defaultCenter] postNotificationName:kInputObjectTextDidChangeNotification object:self]; 
    } 
    

Powiedzmy, że chcemy, aby przywołać klawiaturę w swojej -viewDidAppear:, kod jest następujący:

- (void)viewDidLoad 
    { 
     [super viewDidLoad]; 
     // inputObject and textField are both your ivars in your view controller 
     inputObject = [[InputObject alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
     textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 30)]; 
     inputObject.inputAccessoryView = textField; 
     [self.view addSubview:inputObject]; 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputObjectTextDidChange:) name:kInputObjectTextDidChangeNotification object:nil]; 

    } 

    - (void)viewDidAppear:(BOOL)animated 
    { 
     [super viewDidAppear:animated]; 
     [inputObject becomeFirstResponder]; // This will summon the keyboard 
    } 

Następnie realizacji selektor powiadomienia w kontrolerze widoku:

- (void)inputObjectTextDidChange:(NSNotification *)notification 
    { 
     // Just set the text here. notification.object is actually your inputObject. 
     textField.text = ((InputObject *)(notification.object)).text; 
    } 

To jest chyba to, co masz na myśli przez „ustawić inputAccessoryView bez posiadania UITextField początkowo”

  • Innym rozwiązaniem jest pozwolić textField "udawaj", że jest inputAccessoryView przez ostrożne ułożenie animacji. Ale to rozwiązanie wymaga, aby twój tekst był pierwszą odpowiedzią.

Po pierwsze, należy obserwować zdarzenia klawiatury w -viewDidLoad:

- (void)viewDidLoad 
    { 
     [super viewDidLoad]; 
     // Init the textField and add it as a subview of self.view 
     textField = [[UITextField alloc] init]; 
     textField.backgroundColor = [UIColor redColor]; 
     [self.view addSubview:textField]; 

     // Register keyboard events 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil]; 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil]; 
    } 

drugie, ustawić klatkę textField w -viewWillAppear:, w celu zagwarantowania jej ramkę nie zostaną naruszone przez automatycznej zmiany:

- (void)viewWillAppear:(BOOL)animated 
    { 
     [super viewWillAppear:animated]; 
     textField.frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds), CGRectGetWidth(self.view.bounds), 50); 
    } 

A następnie ułóż animację textField i zsynchronizuj ją z animacją klawiatury. Klawiaturze selektorów powiadomień może być tak:

- (void)keyboardWillShowNotification:(NSNotification *)notification 
    { 
     NSDictionary *userInfo = notification.userInfo; 
     UIViewAnimationCurve curve = [[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]; 
     CGFloat duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; 
     CGRect keyboardFrame = [[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
     keyboardFrame = [self.view convertRect:keyboardFrame toView:self.view]; 

     [UIView animateWithDuration:duration delay:0.0f options:(UIViewAnimationOptions)curve animations:^{ 
      CGRect textFieldFrame = textField.frame; 
      textFieldFrame.origin.y = keyboardFrame.origin.y - CGRectGetHeight(textFieldFrame); 
      textField.frame = textFieldFrame; 
     }completion:nil]; 
    } 

    - (void)keyboardWillHideNotification:(NSNotification *)notification 
    { 
     NSDictionary *userInfo = notification.userInfo; 
     UIViewAnimationCurve curve = [[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]; 
     CGFloat duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; 
     [UIView animateWithDuration:duration delay:0.0f options:(UIViewAnimationOptions)curve animations:^{ 
      textField.frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds), CGRectGetWidth(self.view.bounds), 50); 
     }completion:nil]; 
    } 

W końcu zadzwonić [textField becomeFirstResponder] wywołać animację.

1

Wersja Swift z ograniczeniami autolayout na podstawie odpowiedzi Liuyaodonga.

Wymaga, aby między spodem ekranu a widokiem tekstowym było ustawione pionowe ograniczenie przestrzeni. Zauważ, że ustawienie offsetu musi nastąpić poza kontekstem animacji i tylko układ dzieje się w kontekście animacji.

@IBOutlet weak var textViewBottomOffsetConstraint: NSLayoutConstraint! 

override public func viewDidLoad() { 
    super.viewDidLoad() 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil) 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) 
} 

func keyboardWillHide(notification: NSNotification) { 
    guard let userInfo = notification.userInfo else { 
     return 
    } 

    animateTextFieldOffset(0, userInfo: userInfo) 
} 

func keyboardWillShow(notification: NSNotification) { 
    guard let userInfo = notification.userInfo, var keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() else { 
     return 
    } 

    keyboardFrame = view.convertRect(keyboardFrame, toView: view) 

    animateTextFieldOffset(keyboardFrame.size.height, userInfo: userInfo) 
} 

func animateTextFieldOffset(offset: CGFloat, userInfo: [NSObject: AnyObject]){ 
    guard let animationCurveInt = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int, let animationCurve = UIViewAnimationCurve(rawValue:animationCurveInt) else { return } 

    guard let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double else { return } 

    self.loginViewBottomOffsetConstraint.constant = offset 

    UIView.beginAnimations(nil, context: nil) 
    UIView.setAnimationDuration(animationDuration) 
    UIView.setAnimationCurve(animationCurve) 
    UIView.setAnimationBeginsFromCurrentState(true) 
    self.view.layoutIfNeeded() 
    UIView.commitAnimations() 
} 
+0

Nadal pracuję nad tym, ale wygląda na to, że jest napisane przy użyciu starszej wersji Swift. Dla każdego, kto się na to patrzy, oto post na NotificationCenter addObserver dla Swift 3 http://stackoverflow.com/a/38615219/937682 – Mathieson

Powiązane problemy