Câu hỏi Làm thế nào tôi có thể làm cho một UITextField di chuyển lên khi bàn phím có mặt?


Với SDK iOS:

tôi có một UIView với UITextFields mang đến một bàn phím. Tôi cần nó để có thể:

  1. Cho phép cuộn nội dung của UIScrollView để xem các trường văn bản khác khi bàn phím được đưa lên

  2. Tự động "nhảy" (bằng cách cuộn lên) hoặc rút ngắn

Tôi biết rằng tôi cần một UIScrollView. Tôi đã thử thay đổi lớp học của tôi UIView đến một UIScrollView nhưng tôi vẫn không thể cuộn hộp văn bản lên hoặc xuống.

Tôi có cần cả hai UIView và một UIScrollView? Có ai đi vào bên trong khác không?

Những gì cần phải được thực hiện để tự động di chuyển đến trường văn bản đang hoạt động?

Lý tưởng nhất là thiết lập của các thành phần càng tốt sẽ được thực hiện trong Interface Builder. Tôi chỉ muốn viết mã cho những gì cần.

Lưu ý: các UIView (hoặc là UIScrollView) mà tôi đang làm việc với được đưa lên bởi một thanh tabbar (UITabBar), cần hoạt động như bình thường.


Chỉnh sửa: Tôi đang thêm thanh cuộn chỉ khi bàn phím xuất hiện. Mặc dù nó không cần thiết, tôi cảm thấy nó cung cấp một giao diện tốt hơn bởi vì sau đó người dùng có thể cuộn và thay đổi hộp văn bản, ví dụ.

Tôi đã có nó làm việc, nơi tôi thay đổi kích thước khung của UIScrollView khi bàn phím lên và xuống. Tôi chỉ đơn giản là sử dụng:

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
                     scrollView.frame.origin.y, 
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
       scrollView.frame.origin.y, 
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}

Tuy nhiên, điều này không tự động "di chuyển lên" hoặc căn giữa các trường văn bản thấp hơn trong vùng hiển thị, đó là những gì tôi thực sự muốn.


1558


gốc


Kiểm tra này ra. Không có rắc rối cho bạn. TPKeyboardAvoiding - ArunaLK
Đó là tài liệu của Apple, tôi nghĩ đó là cách tốt nhất: developer.apple.com/library/ios/#documentation/StringsTextFonts/… - Maik639
Sử dụng mã này.Bạn chỉ cần 1 dòng trong tệp appdelegate.m và nó hoạt động. github.com/hackiftekhar/IQKeyboardManager - Pradeep Mittal
Cách tốt nhất tôi tìm thấy cho đến nay là nguồn mở này TPKeyboardAvoiding - Mongi Zaidi
Một cách khác là thêm các trường văn bản nội dung đó và tất cả trong TableViewController và để cho tableview xử lý việc này. - Vicky Dhas


Các câu trả lời:


  1. Bạn sẽ chỉ cần một ScrollView nếu nội dung bạn có bây giờ không vừa với màn hình iPhone. (Nếu bạn đang thêm ScrollView như giám sát của các thành phần. chỉ để làm cho TextField di chuyển lên khi bàn phím xuất hiện, sau đó không cần thiết.)

  2. Để hiển thị textfields mà không bị ẩn bởi bàn phím, cách tiêu chuẩn là di chuyển lên / xuống chế độ xem có textfield bất cứ khi nào bàn phím được hiển thị.

Dưới đây là một số mã mẫu:

#define kOFFSET_FOR_KEYBOARD 80.0

-(void)keyboardWillShow {
    // Animate the current view out of the way
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)keyboardWillHide {
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:mailTf])
    {
        //move the main view, so that the keyboard does not hide it.
        if  (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
    }
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view

    CGRect rect = self.view.frame;
    if (movedUp)
    {
        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.
        rect.origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
    }
    else
    {
        // revert back to the normal state.
        rect.origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
    }
    self.view.frame = rect;

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

971



_TextField là gì? Tôi sao chép nó vào mã của tôi, nó nói _textField là không khai báo. - Cocoa Dev
Đó là trường mà bạn sử dụng để nói "khi người dùng đang chỉnh sửa ở đây chế độ xem nên trượt lên" hoặc một cái gì đó như vậy ... Tuy nhiên, bạn có thể xóa điều đó nếu, nếu bạn có nhiều trường hơn. - patrick
Không đặc biệt hữu ích nếu bạn đang hỗ trợ chế độ xoay của chế độ xem chính. - FiddleMeRagged
Để thực hiện công việc này, tôi phải bình luận textFieldDidBeginEditing phần. - avance
Xấu khi sử dụng kích thước bàn phím cứng. - Jonny


Tôi cũng gặp rất nhiều vấn đề với UIScrollView soạn nhiều UITextFields, trong đó, một hoặc nhiều người trong số họ sẽ bị che khuất bởi bàn phím khi họ đang được chỉnh sửa.

Dưới đây là một số điều cần cân nhắc nếu UIScrollView không di chuyển đúng cách.

1) Đảm bảo rằng contentSize của bạn lớn hơn UIScrollView kích thước khung hình. Cách hiểu UIScrollViews nó có phải là UIScrollView giống như một cửa sổ xem trên nội dung được xác định trong contentSize. Vì vậy, khi để cho UIScrollview để cuộn bất kỳ đâu, contentSize phải lớn hơn UIScrollView. Khác, không có cuộn yêu cầu như tất cả mọi thứ được xác định trong contentSize đã được nhìn thấy. BTW, mặc định contentSize = CGSizeZero.

2) Bây giờ bạn hiểu rằng UIScrollView thực sự là một cửa sổ vào "nội dung" của bạn, cách để đảm bảo rằng bàn phím không che khuất UIScrollView's xem "cửa sổ" sẽ thay đổi kích thước UIScrollView để khi có bàn phím, bạn có UIScrollView cửa sổ có kích thước chỉ là bản gốc UIScrollView frame.size.height trừ đi chiều cao của bàn phím. Điều này sẽ đảm bảo rằng cửa sổ của bạn chỉ là khu vực nhỏ có thể xem được.

3) Đây là bắt: Khi tôi lần đầu tiên thực hiện điều này tôi đã tìm tôi sẽ phải có được CGRect của trường văn bản đã chỉnh sửa và cuộc gọi UIScrollView's phương thức scrollRecToVisible. Tôi đã triển khai UITextFieldDelegate phương pháp textFieldDidBeginEditing với cuộc gọi đến scrollRecToVisible phương pháp. Điều này thực sự làm việc với một hiệu ứng phụ lạ mà cuộn sẽ chụp các UITextField vào vị trí. Trong thời gian dài nhất tôi không thể hiểu được nó là gì. Sau đó tôi nhận xét textFieldDidBeginEditing Phương thức ủy nhiệm và tất cả đều hoạt động !! (???). Khi nó bật ra, tôi tin rằng UIScrollView thực sự ngầm mang đến hiện tại đã được chỉnh sửa UITextField vào cửa sổ có thể xem được. Việc triển khai của tôi về UITextFieldDelegate phương pháp và cuộc gọi tiếp theo đến scrollRecToVisible là dư thừa và là nguyên nhân gây ra tác dụng phụ lạ lùng.

Vì vậy, đây là các bước để cuộn đúng cách UITextField trong một UIScrollView vào vị trí khi bàn phím xuất hiện.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    CGSize scrollContentSize = CGSizeMake(320, 345);
    self.scrollView.contentSize = scrollContentSize;
}

- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. Đăng ký thông báo bàn phím tại viewDidLoad
  2. Hủy đăng ký cho nofitications bàn phím tại viewDidUnload
  3. Đảm bảo rằng contentSize được đặt và lớn hơn UIScrollView tại viewDidLoad
  4. Co lại các UIScrollView khi bàn phím có mặt
  5. Hoàn nguyên lại các UIScrollView khi bàn phím biến mất.
  6. Sử dụng một chiếc ngà để phát hiện xem bàn phím đã được hiển thị trên màn hình vì thông báo bàn phím được gửi mỗi lần UITextField được gắn thẻ ngay cả khi bàn phím đã có mặt để tránh co lại các UIScrollView khi nó đã thu nhỏ

Một điều cần lưu ý là UIKeyboardWillShowNotification sẽ kích hoạt ngay cả khi bàn phím đã có trên màn hình khi bạn đặt tab trên bàn phím khác UITextField. Tôi đã chăm sóc điều này bằng cách sử dụng một chiếc ngà để tránh thay đổi kích cỡ UIScrollView khi bàn phím đã có trên màn hình. Vô tình đổi kích thước UIScrollView khi bàn phím đã có sẽ là thảm họa!

Hy vọng mã này giúp bạn tiết kiệm rất nhiều đau đầu.


437



Tuyệt, nhưng hai vấn đề: 1. UIKeyboardBoundsUserInfoKey không được chấp nhận. 2. keyboardSize nằm trong "tọa độ màn hình", vì vậy các phép tính khung nhìn của bạn sẽ thất bại nếu khung được xoay hoặc thu nhỏ. - Martin Wickman
@Martin Wickman - Sử dụng CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; thay vì không dùng nữa UIKeyboardBoundsUserInfoKey - sottenad
HI, tôi cũng làm như vậy, nhưng chế độ xem văn bản chỉ chuyển lên khi người dùng bắt đầu nhập? Đó có phải là hành vi mong đợi hoặc tôi đang thiếu cái gì đó?
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size nên là [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size . Giải pháp tuyệt vời mặc dù! - j7nn7k
Tôi thích giải pháp của bạn nhưng tôi nghĩ rằng tôi có thể làm cho nó thậm chí còn đơn giản hơn: không bận tâm với các công cụ thông báo Observer; thay vào đó hãy gọi các thói quen hoạt hình phù hợp bên trong các phương thức đại biểu phù hợp - cho UITextView chúng là textViewDidBeginEditing và textViewDidEndEditing. - AlexChaffee


Nó thực sự tốt nhất chỉ để sử dụng thực hiện của Apple, như được cung cấp trong tài liệu. Tuy nhiên, mã họ cung cấp bị lỗi. Thay thế phần được tìm thấy trong keyboardWasShown: ngay bên dưới các bình luận sau đây:

NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint origin =  activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
    CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}

Các vấn đề với mã của Apple là: (1) Họ luôn tính toán nếu điểm nằm trong khung của khung nhìn, nhưng đó là ScrollView, do đó, nó có thể đã cuộn và bạn cần phải tính toán cho bù đắp đó:

origin.y -= scrollView.contentOffset.y

(2) Họ thay đổi contentOffset bằng chiều cao của bàn phím, nhưng chúng tôi muốn đối diện (chúng tôi muốn thay đổi contentOffset theo chiều cao hiển thị trên màn hình, không phải thứ gì không):

activeField.frame.origin.y-(aRect.size.height)

260



Trong trường hợp chế độ xem cuộn không làm đầy màn hình, aRect sẽ được đặt thành khung của chế độ xem cuộn - mblackwell8
Không nên bạn muốn CGPoint origin = activeField.frame.origin + activeField.frame.size.height?, Bởi vì bạn muốn toàn bộ textfield được hiển thị và nếu nó chỉ xuất hiện một số pixel thì mã sẽ không nhập điều kiện. - htafoya
Giải pháp này không hoạt động theo hướng ngang - trường văn bản bay ra khỏi đầu của cổng xem. iPad với iOS 7.1. - Andrew
Để được hỗ trợ iOS 8 tốt hơn, tôi khuyên bạn nên sử dụng UIKeyboardFrameEndUserInfoKey thay vì UIKeyboardFrameBeginUserInfoKey khi nhận được kích thước bàn phím, vì điều này sẽ nhận những thứ như thay đổi bàn phím tùy chỉnh và bật / tắt văn bản tiên đoán. - Endareth
@Egor: Sửa chữa của bạn làm cho nó hoạt động tốt hơn - nhưng dòng cuối cùng phải là nghịch đảo: self.scrollView.contentOffset = self.currentSVoffset; - Morten Holmgaard


Trong textFieldDidBeginEditting và trong textFieldDidEndEditing gọi hàm [self animateTextField:textField up:YES] như vậy:

-(void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    [self animateTextField:textField up:YES]; 
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField:textField up:NO];
}

-(void)animateTextField:(UITextField*)textField up:(BOOL)up
{
    const int movementDistance = -130; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

    int movement = (up ? movementDistance : -movementDistance); 

    [UIView beginAnimations: @"animateTextField" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}

Tôi hy vọng mã này sẽ giúp bạn.

Trong Swift 2

func animateTextField(textField: UITextField, up: Bool) 
{
     let movementDistance:CGFloat = -130
     let movementDuration: Double = 0.3

     var movement:CGFloat = 0
     if up 
     {
         movement = movementDistance
     }
     else 
     {
         movement = -movementDistance
     }
     UIView.beginAnimations("animateTextField", context: nil)
     UIView.setAnimationBeginsFromCurrentState(true)
     UIView.setAnimationDuration(movementDuration)
     self.view.frame = CGRectOffset(self.view.frame, 0, movement)
     UIView.commitAnimations()
}


func textFieldDidBeginEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:true)
}

func textFieldDidEndEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:false)
}

SWIFT 3

 func animateTextField(textField: UITextField, up: Bool)
    {
        let movementDistance:CGFloat = -130
        let movementDuration: Double = 0.3

        var movement:CGFloat = 0
        if up
        {
            movement = movementDistance
        }
        else
        {
            movement = -movementDistance
        }
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(movementDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }


    func textFieldDidBeginEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:true)
    }

    func textFieldDidEndEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:false)
    }

238



tại sao không sử dụng [UIView animateWithDuration: animations:^{ }]; ? - André Cytryn
điều này hoạt động tốt, mặc dù const int movementDistance = -130; // tinh chỉnh khi cần thiết cần được thay đổi thành linh hoạt hơn - Hammer
Cực kỳ đơn giản về triển khai nhỏ. Không mucking xung quanh với ScrollViews và các vấn đề bố cục tự động không rõ ràng. - James Perih
Erm ... bạn không sử dụng tham số textField chút nào. Tại sao sau đó có nó như là một tham số chức năng? Ngoài ra, bạn có thể sử dụng toán tử ternary cũng trong Swift. Làm cho mã ít nói. - stk
Nếu màu nền của Chế độ xem là một thứ khác với màu đen, hãy đảm bảo bạn đặt màu của Cửa sổ để khớp với chế độ xem của bạn để người dùng không nhìn thấy phía sau nó. ví dụ: self.window.backgroundColor = [UIColor whiteColor]; - bvmobileapps


Chỉ cần sử dụng TextFields:

1a) Sử dụng Interface Builder: Chọn Tất cả TextFields => Chỉnh sửa => Nhúng trong => ScrollView

1b) nhúng thủ công TextFields trong UIScrollView gọi là scrollView

2 bộ UITextFieldDelegate

3) Đặt mỗi textField.delegate = self; (hoặc tạo kết nối Interface Builder)

4) Sao chép dán:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [scrollView setContentOffset:CGPointZero animated:YES];
}

133



Nhưng nó cũng làm tăng tầm nhìn khi textField đã được hiển thị. - TheTiger
Cần thay đổi CGPointMake(0, textField.frame.origin.y);đến CGPointMake(0, textField.frame.origin.y + scrollView.contentInset.top); - Egor T
@Egor Ngay cả sau khi bình luận của bạn nó không hoạt động. Giống như "TheTiger" đề cập đến nó di chuyển lên xem ngay cả sau khi textfield có thể nhìn thấy. - rak appdev


Dành cho Giải pháp toàn cầu, Đây là cách tiếp cận của tôi để triển khai IQKeyboardManager.

enter image description here

Bước 1:- Tôi đã thêm thông báo toàn cầu về UITextField, UITextViewUIKeyboard trong một lớp singleton. Tôi gọi nó là IQKeyboardManager.

Bước 2:- Nếu được tìm thấy UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification hoặc là UITextViewTextDidBeginEditingNotification thông báo, tôi cố gắng để có được topMostViewController ví dụ từ UIWindow.rootViewController hệ thống cấp bậc. Để phát hiện đúng cách UITextField/UITextView trên đó, topMostViewController.viewKhung của cần phải được điều chỉnh.

Bước 3:- Tôi tính toán khoảng cách di chuyển dự kiến ​​của topMostViewController.view đối với câu trả lời đầu tiên UITextField/UITextView.

Bước 4:- Tôi đã di chuyển topMostViewController.view.frame lên / xuống theo khoảng cách di chuyển dự kiến.

Bước 5: - Nếu được tìm thấy UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification hoặc là UITextViewTextDidEndEditingNotification thông báo, tôi một lần nữa cố gắng để có được topMostViewController ví dụ từ UIWindow.rootViewController hệ thống cấp bậc.

Bước 6: - Tôi tính khoảng cách bị xáo trộn của topMostViewController.view cần được khôi phục về vị trí ban đầu của nó.

Bước 7: - Tôi đã khôi phục topMostViewController.view.frame xuống theo khoảng cách bị xáo trộn.

Bước 8: - Tôi đã thuyết minh singleton IQKeyboardManager thể hiện lớp trên tải ứng dụng, vì vậy mọi UITextField/UITextView trong ứng dụng sẽ tự động điều chỉnh theo khoảng cách di chuyển dự kiến.

Đó là tất cả IQKeyboardManager làm cho bạn với KHÔNG CÓ DÒNG Màcó thật không!! chỉ cần kéo và thả tệp nguồn có liên quan vào dự án. IQKeyboardManager cũng hỗ trợ Định hướng thiết bị, Quản lý UIToolbar tự động, KeybkeyboardDistanceFromTextField và nhiều hơn bạn nghĩ.


106



Thêm thư mục IQKeyBoardManagerSwift vào dự án của tôi và không hoạt động. Không thể bật cuz nó không nhận ra trong AppDelegate ... - user3722523
điều này cảm thấy như lừa đảo các giải pháp thực tế không được hiển thị nhưng thay vào đó chúng ta thấy một thương mại cho tài khoản này GitHub kẻ. - Brian


Tôi đã tổng hợp lại, thả vào UIScrollView, UITableView và ngay cả UICollectionView lớp con sẽ chăm sóc di chuyển tất cả các trường văn bản bên trong nó ra khỏi bàn phím.

Khi bàn phím sắp xuất hiện, lớp con sẽ tìm thấy chế độ xem con sắp được chỉnh sửa và điều chỉnh khung và nội dung bù đắp để đảm bảo rằng chế độ xem hiển thị, với hoạt ảnh khớp với cửa sổ bật lên bàn phím. Khi bàn phím biến mất, nó sẽ khôi phục kích thước trước của nó.

Nó sẽ làm việc với bất kỳ thiết lập cơ bản nào, hoặc là UITableViewdựa trên giao diện, hoặc một bao gồm các khung nhìn được đặt thủ công.

Đây là tis: giải pháp để di chuyển các trường văn bản ra khỏi bàn phím


99



Đây chính là nó! Đây là giải pháp tốt nhất, hiệu quả nhất và hoàn hảo nhất! Nó cũng xử lý luân phiên đúng cách cho chế độ xem cuộn. Nếu xoay chắc chắn để tự động theo chiều dọc nhưng không neo ở phía dưới. Tôi đã thêm UITextView vào chế độ xem cuộn trong trường hợp của tôi. Thanks bunches! - Christopher
Công việc rất tốt! Chắc chắn, tôi đang lười biếng bằng cách sử dụng giải pháp của bạn thay vì một trong những DIY, nhưng ông chủ của tôi là hạnh phúc hơn, vì vậy yeah! Thậm chí nếu ai đó muốn tự làm, tôi thích cách tiếp cận phân lớp của bạn, thay vì thêm mã vào mỗi bộ điều khiển. Tôi đã bị sốc iOS đã không làm điều này theo mặc định như Android đã làm - sau đó một lần nữa, tôi đang tìm thấy rất nhiều thứ thiếu trong iOS và MacOS: ( - eselk
Tôi đã dành cả ngày hôm qua cố gắng để có được một trong những câu trả lời khác để làm việc (cố gắng tránh thêm một thư viện toàn bộ). Hôm nay tôi cắm nó vào, ngoại trừ công việc tối thiểu, nó hoạt động tốt. Bởi công việc tối thiểu tôi có nghĩa là đổi tên scrollviews của tôi như TPKeyboardAvoidingScrollView - learner
Có những thứ kỳ lạ như scrollview của tôi tất cả phù hợp trong màn hình, vì vậy nó không thể được cuộn. Sau khi mở và đóng bàn phím, nội dung bây giờ lớn hơn (trông giống như một cái gì đó vô hình đã được thêm vào và không được gỡ bỏ ở dưới cùng của trang), và có thể được cuộn. - Almo


Dành cho Nhanh Lập trình viên:

Điều này sẽ làm mọi thứ cho bạn, chỉ cần đặt chúng trong lớp trình điều khiển xem của bạn và thực hiện UITextFieldDelegate vào bộ điều khiển chế độ xem của bạn và đặt đại biểu của textField thành self 

textField.delegate = self // Setting delegate of your UITextField to self

Thực hiện các phương thức gọi lại đại biểu:

func textFieldDidBeginEditing(textField: UITextField) {
    animateViewMoving(true, moveValue: 100)
}

func textFieldDidEndEditing(textField: UITextField) {
    animateViewMoving(false, moveValue: 100)
}

// Lifting the view up
func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration )
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}

84



SwiftLint không thích self.view.frame = CGRectOffset(self.view.frame, 0, movement) vì vậy tôi đã thay đổi dòng đó thành self.view.frame.offsetInPlace(dx: 0, dy: movement) - levibostian
Swift 4 thay đổi self.view.frame = CGRectOffset (self.view.frame, 0, chuyển động) thành self.view.frame.offsetBy (dx: 0, dy: movement) - Asinox


Đã có rất nhiều câu trả lời, nhưng vẫn không có giải pháp nào ở trên có tất cả các công cụ định vị ưa thích được yêu cầu cho hoạt ảnh không có lỗi "hoàn hảo", tương thích ngược và nhấp nháy. (lỗi khi tạo khung hình / giới hạn và contentOffset cùng nhau, định hướng giao diện khác nhau, bàn phím chia iPad, ...)
Hãy để tôi chia sẻ giải pháp của tôi:
(giả sử bạn đã thiết lập UIKeyboardWill(Show|Hide)Notification)

// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = [notification userInfo];

    CGRect keyboardFrameInWindow;
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];

    // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
    CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];

    CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
    UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);

    // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    _scrollView.contentInset = newContentInsets;
    _scrollView.scrollIndicatorInsets = newContentInsets;

    /*
     * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
     * that should be visible, e.g. a purchase button below an amount text field
     * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
     */
    if (_focusedControl) {
        CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
        controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view.

        CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y;
        CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;

        // this is the visible part of the scroll view that is not hidden by the keyboard
        CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;

        if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
            // scroll up until the control is in place
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);

            // make sure we don't set an impossible offset caused by the "nice visual offset"
            // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
            newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        } else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) {
            // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y = controlFrameInScrollView.origin.y;

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        }
    }

    [UIView commitAnimations];
}


// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = notification.userInfo;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    // undo all that keyboardWillShow-magic
    // the scroll view will adjust its contentOffset apropriately
    _scrollView.contentInset = UIEdgeInsetsZero;
    _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;

    [UIView commitAnimations];
}

61



Những cải tiến tuyệt vời của câu trả lời @Shiun. Nhưng sau khi bàn phím đã biến mất, chế độ xem không quay lại ở vị trí thứ nhất. Nó vẫn là một công việc tuyệt vời :) - Lucien
Cảm ơn, đây là giải pháp tốt nhất cho tôi trong năm 2017. Lưu ý rằng bạn không cần phải theo dõi tập trungControl mình, bạn có thể xác định rằng với UIApplication.shared.sendAction(...). Đây là phiên bản Swift 3 của câu trả lời của bạn (trừ phần willHide), với sendAction triển khai: gist.github.com/xaphod/7aab1302004f6e933593a11ad8f5a72d - xaphod
@xaphod trong trường hợp của tôi, tôi cần tập trung nhiều điều khiển hơn - ví dụ: một nút bên dưới trường nhập. nhưng vâng mã đó bây giờ đã 4 tuổi và có thể hưởng lợi từ những cải tiến. - Martin Ullrich