2013-08-15 33 views

Trả lời

1

Giải pháp hacky cho vấn đề này là có UITextField trong chế độ xem nhưng ẩn và sau đó gọi [textfield trở thànhFirstResponder] trên đó.

tôi chỉ thử nghiệm nó và điều này làm việc

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]; 

Bạn cần phải có đó là một subview của quan điểm khác này sẽ không hoạt động.

5

Một giải pháp khác là thêm những phương pháp để UIViewController thực hiện của bạn:

- (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; 
} 

và thêm biến _textField để giao diện của bạn:

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

Bạn không thể triệu tập các bàn phím mà không một đối tượng mà có thể trở thành người trả lời đầu tiên. Có hai cách để làm việc xung quanh:

  • Subclass một UIView và thực hiện UIKeyInput giao thức trong đó. Ví dụ:

    Trong file .h của bạn:

    @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 
    

    Trong file .m của bạn, thực hiện các giao thức:

    - (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]; 
    } 
    

Hãy nói rằng bạn muốn triệu tập bàn phím trong của bạn -viewDidAppear:, mã như sau:

- (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 
    } 

Sau đó thực hiện các selector thông báo trong điều khiển điểm của bạn:

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

Đây có lẽ là những gì bạn có ý nghĩa bởi "thiết lập inputAccessoryView mà không cần một UITextField ban đầu"

  • workaround khác là để cho các TextField "giả vờ" là inputAccessoryView bằng cách sắp xếp cẩn thận hoạt ảnh của nó. Nhưng giải pháp này cần textField của bạn là người trả lời đầu tiên.

Thứ nhất, bạn quan sát các sự kiện bàn phím trong -viewDidLoad của bạn:

- (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]; 
    } 

Thứ hai, thiết lập khung textField của bạn trong -viewWillAppear:, để đảm bảo khung của nó sẽ không bị ảnh hưởng bởi autoresizing:

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

Sau đó, sắp xếp hoạt ảnh textField của bạn và để nó được đồng bộ hóa với hoạt ảnh bàn phím. Bộ chọn thông báo bàn phím của bạn có thể như sau:

- (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]; 
    } 

Cuối cùng, hãy gọi [textField becomeFirstResponder] để kích hoạt hoạt ảnh.

1

Phiên bản Swift sử dụng các hạn chế tự động trả lời dựa trên câu trả lời của liuyaodong.

Yêu cầu bạn có thiết lập ràng buộc không gian dọc giữa phần dưới cùng của màn hình và chế độ xem văn bản. Lưu ý rằng việc đặt bù trừ phải xảy ra bên ngoài ngữ cảnh hoạt ảnh và chỉ bố cục xảy ra bên trong ngữ cảnh hoạt ảnh.

@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

Vẫn đang làm việc theo cách này thông qua đây, nhưng có vẻ như điều này được viết bằng phiên bản cũ hơn của Swift. Đối với bất cứ ai nhìn vào đây, đây là một bài đăng trên NotificationCenter addObserver cho Swift 3 http://stackoverflow.com/a/38615219/937682 – Mathieson

Các vấn đề liên quan