كيف يمكنني جعل UITextField تتحرك حتى عندما تكون لوحة المفاتيح الحالية على الانطلاق إلى تحرير ؟

StackOverflow https://stackoverflow.com/questions/1126726

سؤال

مع دائرة الرقابة الداخلية SDK:

لدي UIView مع UITextFields أن إظهار لوحة المفاتيح.أنا بحاجة إلى أن يكون قادرا على:

  1. يسمح التمرير من محتويات UIScrollView لرؤية باقي حقول النص مرة واحدة لوحة المفاتيح ترعرعت

  2. تلقائيا "القفز" (عن طريق التمرير صعودا) أو تقصير

وأنا أعلم أنني بحاجة إلى UIScrollView.لقد حاولت تغيير فئة من بلدي UIView إلى UIScrollView ولكن أنا لا تزال غير قادرة على تمرير مربعات النص لأعلى أو لأسفل.

هل أنا بحاجة على حد سواء UIView و UIScrollView?لا دفعة واحدة داخل الأخرى ؟

ما يجب تنفيذها من أجل تلقائيا انتقل إلى نشطة نص الملعب ؟

من الناحية المثالية قدر من الإعداد المكونات ممكن يكون في واجهة البناء.أود فقط كتابة كود من أجل ما يحتاج إليه.

ملاحظة:على UIView (أو UIScrollView) أن أعمل مع ترعرعت قبل tabbar (UITabBar) ، والتي يجب أن تعمل بشكل طبيعي.


تحرير:انا إضافة شريط التمرير فقط عندما تكون لوحة المفاتيح يأتي.على الرغم من أنه لا حاجة ، أشعر أنه يوفر واجهة أفضل لأن ثم يمكن للمستخدم التنقل وتغيير مربعات النص ، على سبيل المثال.

لقد حصلت على هذا العمل حيث يمكنني تغيير حجم الإطار من UIScrollView عندما تكون لوحة المفاتيح يذهب صعودا وهبوطا.أنا ببساطة عن طريق استخدام:

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

ولكن هذا لا تلقائيا "تحريك لأعلى" أو مركز أقل حقول النص في المنطقة المرئية, وهو ما أود حقا.

هل كانت مفيدة؟

المحلول

  1. سوف تحتاج فقط ScrollView إذا كانت المحتويات التي لديك الآن لا تناسب شاشة iPhone. (إذا كنت تضيف ScrollView كما superview للمكونات. فقط لجعل TextField التمرير لأعلى عندما تأتي لوحة المفاتيح، ثم ليست هناك حاجة إليها.)

  2. لإظهار ذلك textfields بدون إخفاء لوحة المفاتيح، فإن الطريقة القياسية هي نقل UP / DOWN عرض النصوص عند إظهار لوحة المفاتيح.

إليك بعض نماذج الشفرة:

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

نصائح أخرى

أنا أيضا وجود الكثير من المسألة UIScrollView تأليف متعددة UITextFields, منها واحد أو أكثر منهم الحصول على تحجب لوحة المفاتيح عندما يتم تحريرها.

وهنا بعض الأشياء في الاعتبار إذا كان الخاص بك UIScrollView ليس صحيح التمرير.

1) التأكد من أن contentSize أكبر من UIScrollView حجم الإطار.الطريق إلى فهم UIScrollViews هو أن UIScrollView مثل نافذة عرض على محتوى المعرفة في contentSize.حتى عندما تكون في أجل UIScrollview انتقل إلى أي مكان ، contentSize يجب أن تكون أكبر من UIScrollView.آخر, لا يوجد التمرير المطلوبة كما كل شيء المحددة في contentSize بالفعل مرئية.راجع للشغل, default contentSize = CGSizeZero.

2) الآن عليك أن تفهم أن UIScrollView هو حقا نافذة في "المحتوى" ، طريقة للتأكد من أن لوحة المفاتيح ليست إعاقة UIScrollView's عرض "الإطار" أن حجم UIScrollView بحيث عندما تكون لوحة المفاتيح موجودة لديك UIScrollView نافذة الحجم الأصلي فقط UIScrollView الإطار.الحجم.ارتفاع ناقص ارتفاع لوحة المفاتيح.هذا يضمن لك النافذة الصغيرة مساحة للعرض.

3) هنا هو الصيد:عندما كنت أول من ينفذ هذا فكرت أن تحصل على CGRect المحرر النصي و الاتصال UIScrollView's scrollRecToVisible الأسلوب.لقد نفذت UITextFieldDelegate طريقة textFieldDidBeginEditing مع الدعوة إلى scrollRecToVisible الأسلوب.هذا فعلا عملت مع غريب الآثار الجانبية التمرير سوف snap على UITextField في الموقف.لفترة طويلة لم أتمكن من معرفة ما كان عليه.ثم علقت بها textFieldDidBeginEditing مندوب طريقة و كل عمل!!(???).كما اتضح ، وأعتقد أن UIScrollView فعلا ضمنا يجلب حاليا تحريرها UITextField في نافذة للعرض ضمنا.بلدي تنفيذ UITextFieldDelegate طريقة اللاحقة الدعوة إلى scrollRecToVisible زائدة و كان سبب غريب الآثار الجانبية.

حتى هنا هي الخطوات بشكل صحيح انتقل الخاص بك UITextField في UIScrollView في مكانها عندما تظهر لوحة المفاتيح.

// 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. تسجيل لوحة المفاتيح الإخطارات في viewDidLoad
  2. إلغاء تسجيل لوحة المفاتيح nofitications في viewDidUnload
  3. ضمان contentSize هو مجموعة أكبر من UIScrollView في viewDidLoad
  4. يتقلص على UIScrollView عندما تكون لوحة المفاتيح الحالية
  5. العودة على UIScrollView عندما تكون لوحة المفاتيح يذهب بعيدا.
  6. استخدام ايفار للكشف إذا كان المفاتيح بالفعل تظهر على الشاشة منذ المفاتيح يتم إرسال إشعارات في كل مرة UITextField هو كلفه حتى لو كانت لوحة المفاتيح موجودة بالفعل لتجنب تقلص على UIScrollView عندما يكون بالفعل تقلصت

شيء واحد هو أن نلاحظ أن UIKeyboardWillShowNotification سوف النار حتى عندما تكون لوحة المفاتيح على الشاشة عندما كنت التبويب على آخر UITextField.أخذت الرعاية من هذا باستخدام ايفار لتجنب تغيير حجم UIScrollView عندما تكون لوحة المفاتيح على الشاشة.عن غير قصد تغيير حجم UIScrollView عندما تكون لوحة المفاتيح هو بالفعل هناك ستكون كارثية!

نأمل أن يكون هذا رمز يحفظ بعض من لك الكثير من الصداع.

من الأفضل فعلا فقط استخدام تنفيذ أبل، على النحو المنصوص عليه في مستندات. وبعد ومع ذلك، فإن الرمز الذي يقدمونه هو معيب. استبدال الجزء الموجود في keyboardWasShown: أسفل التعليقات التالية التالية:

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

مشاكل رمز Apple هي: (1) يحسبون دائما إذا كانت النقطة داخل إطار العرض، لكنه ScrollView, ، لذلك قد يكون بالفعل تمرير وتحتاج إلى حساب تلك الإزاحة:

origin.y -= scrollView.contentOffset.y

(2) يحولون المحتوى عن طريق ارتفاع لوحة المفاتيح، لكننا نريد العكس (نريد تحويل contentOffset بواسطة الارتفاع المرئي على الشاشة، وليس ما ليس):

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

في textFieldDidBeginEditting و في textFieldDidEndEditing استدعاء الوظيفة [self animateTextField:textField up:YES] مثل ذلك:

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

آمل أن يساعدك هذا الرمز.

في 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)
}

سويفت 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)
    }

فقط استخدام TextFields:

1A) باستخدام Interface Builder: حدد جميع TextFields => تحرير => تضمينه في => ScrollView

1 ب) تضمين TextFields يدويا في UiscrollView تسمى ScrollView

2) مجموعة UITextFieldDelegate

3) تعيين كل textField.delegate = self; (أو تقديم اتصالات في Interface Builder)

4) نسخ ولصق:

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

ل حل عالمي, ، كان هنا نهجي للتنفيذ iqkeyboardmanager..

enter image description here

الخطوة 1:- أضفت إخطارات عالمية من UITextField, UITextView, ، و UIKeyboard في فئة singleton. اسميها iqkeyboardmanager..

الخطوة 2:- ان وجد UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification أو UITextViewTextDidBeginEditingNotification الإخطارات، أحاول الحصول عليها topMostViewController مثال من UIWindow.rootViewController التسلسل الهرمي. من أجل الكشف بشكل صحيح UITextField/UITextView عليه، topMostViewController.viewيجب ضبط الإطار.

الخطوه 3:- أنا محسوبة نقل المسافة المتوقعة من topMostViewController.view فيما يتعلق بالاستجابة لأول مرة UITextField/UITextView.

Step4: - تحركت topMostViewController.view.frame أعلى / أسفل وفقا لمسافة الخطوة المتوقعة.

الخطوة 5: - ان وجد UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification أو UITextViewTextDidEndEditingNotification إخطار، أنا أحاول مرة أخرى الحصول عليها topMostViewController مثال من UIWindow.rootViewController التسلسل الهرمي.

Step6: - احسبت مسافة مضطربة topMostViewController.view التي يجب استعادتها إلى موقعها الأصلي.

Step7: - استعادت topMostViewController.view.frame أسفل وفقا للمسافة المضطربة.

Step8: - أنا مثيل لأنفرنتون iqkeyboardmanager. مثيل الطبقة على تحميل التطبيق، لذلك كل UITextField/UITextView في التطبيق سوف يتضيف تلقائيا وفقا لمسافة الخطوة المتوقعة.

هذا كل شئ iqkeyboardmanager. هل لا يوجد خط من التعليمات البرمجية هل حقا!! تحتاج فقط إلى سحب وإسقاط ملف المصدر المرتبط إلى المشروع. iqkeyboardmanager. ودعم أيضا اتجاه الجهاز, إدارة UITOOLBAR التلقائي, keybkeyboarddistancefromtextfield. وأكثر من ذلك بكثير مما تعتقد.

لقد وضعت معا عالمي، قطرة UIScrollView, UITableView وحتى UICollectionView Subclass التي تعتني بتحريك جميع الحقول النصية داخلها خارج لوحة المفاتيح.

عندما تكون لوحة المفاتيح على وشك ظهورها، ستجد الفئة الفرعية الفرعية قيد التحرير، وضبط إطارها وإزاحة المحتوى للتأكد من أن هذه الرأي مرئية، مع وجود رسوم متحركة لمطابقة نافذة لوحة المفاتيح. عندما تختفي لوحة المفاتيح، فإنها تعيد حجمها السابق.

يجب أن تعمل مع أي إعداد أساسا، إما UITableViewواجهة المعظم، أو واحدة تتكون من وجهات النظر وضعت يدويا.

هنا TIS: حل نقل الحقول النصية من طريقة لوحة المفاتيح

ل سويفت مبرمجون:

هذا سيفعل كل شيء من أجلك، فقط ضع هذه في فئة وحدة التحكم في رأيك وتنفيذ UITextFieldDelegate لوحدة التحكم الخاصة بك ووضع مندوب textfield ل self

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

تنفيذ أساليب رد المندوب:

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

ل SWIFT 4، 4.2، 5: التغيير

self.view.frame = CGRectOffset(self.view.frame, 0,  movement)

ل

self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)

آخر ملاحظة حول هذا التطبيق: إذا قمت بضغط وحدة تحكم عرض أخرى على المكدس أثناء عرض لوحة المفاتيح، فسيؤدي ذلك إلى إنشاء خطأ حيث يتم إرجاع طريقة العرض مرة أخرى إلى إطار مركزها ولكن لم يتم إعادة تعيين إزاحة لوحة المفاتيح. على سبيل المثال. لإصلاح خطأ الإزاحة، تأكد من استدعاء NameField.ResignFirstresponder () قبل مغادرة وحدة تحكم العرض، مما يضمن استدعاء طريقة مفوض TextFieldDideiting كذلك. أفعل هذا في طريقة ViewWillDisAppear.

هناك بالفعل الكثير من الإجابات، ولكن لا تزال أي من الحلول المذكورة أعلاه كانت كل الأشياء المطلوبة لتحديد المواقع الفاخرة لرسوم متحركة "مثالية" خالية من الأخطاء والخلف متوافقة مع الرسوم المتحركة المتوافقة مع الورق والميض. (علة عند التحريك الإطار / الحدود ومحتوى معا، اتجاهات واجهة مختلفة، لوحة المفاتيح سبليت iPad، ...)
اسمحوا لي أن أشارك الحل الخاص بي:
(على افتراض أنك قد أنشأت 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];
}

قال شيون "كما اتضح، أعتقد أن uiscrollview يؤدي فعلا ضمنيا إلى أن UITEXTFILD الموجود حاليا في النافذة القابلة للعرض ضمنيا" يبدو أن هذا صحيح بالنسبة ل IOS 3.1.3، ولكن ليس 3.2 أو 4.0 أو 4.1. اضطررت إلى إضافة ملف التنظيف الصريح من أجل جعل UITEXTFILD مرئية على iOS> = 3.2.

هذه وثيقة تفاصيل الحل لهذه المشكلة. انظر إلى التعليمات البرمجية المصدر ضمن "المحتوى المتحرك الموجود الموجود أسفل لوحة المفاتيح". انها واضحة جدا.

تحرير: لاحظت وجود خلل WEE في المثال. ربما تريد الاستماع ل UIKeyboardWillHideNotification بدلاً من UIKeyboardDidHideNotification. وبعد وإلا سيتم قص عرض التمرير وراء لوحة المفاتيح لمدة رسوم متحركة إغلاق لوحة المفاتيح.

شيء واحد يجب مراعاته هو ما إذا كنت تريد استخدام أي وقت مضى UITextField من تلقاء نفسها. أنا لم آخذ عبر أي تطبيقات iPhone مصممة بشكل جيد تستخدم في الواقع UITextFields خارج UITableViewCells.

سيكون بعض الأعمال الإضافية، لكنني أوصي بتنفيذ جميع طرق عرض البيانات وجهات نظر جدول. أضف UITextView لك UITableViewCells.

وجد أسهل حل

- (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 = 80; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

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

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

إصلاح صغير يعمل بالنسبة للعديد من UITEXTFields

#pragma mark UIKeyboard handling

#define kMin 150

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
   if (currTextField) {
      [currTextField release];
   }
   currTextField = [sender retain];
   //move the main view, so that the keyboard does not hide it.
   if (self.view.frame.origin.y + currTextField.frame.origin. y >= kMin) {
        [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 = kMin - currTextField.frame.origin.y ;
   }
   else
   {
      // revert back to the normal state.
      rect.origin.y = 0;
   }
   self.view.frame = rect;

   [UIView commitAnimations];
}


- (void)keyboardWillShow:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately

   if ([currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y >= kMin)
   {
      [self setViewMovedUp:YES];
   }
   else if (![currTextField isFirstResponder] && currTextField.frame.origin.y  + self.view.frame.origin.y < kMin)
   {
      [self setViewMovedUp:NO];
   }
}

- (void)keyboardWillHide:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
   if (self.view.frame.origin.y < 0 ) {
      [self setViewMovedUp:NO];
   }

}


- (void)viewWillAppear:(BOOL)animated
{
   // register for keyboard notifications
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) 
                                                name:UIKeyboardWillShowNotification object:self.view.window]; 
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) 
                                                name:UIKeyboardWillHideNotification object:self.view.window]; 
}

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

ينقل رمز RPDP بنجاح حقل النص من طريقة لوحة المفاتيح. ولكن عند التمرير إلى الأعلى بعد استخدام لوحة المفاتيح ورفضها، تم تمرير الأعلى من العرض. هذا صحيح بالنسبة للمحاكاة والجهاز. لقراءة المحتوى في الجزء العلوي من هذا الرأي، يتعين على المرء إعادة تحميل العرض.

أليس الكود التالي من المفترض أن يجلب الرأي مرة أخرى؟

else
{
    // revert back to the normal state.
    rect.origin.y += kOFFSET_FOR_KEYBOARD;
    rect.size.height -= kOFFSET_FOR_KEYBOARD;
}

لست متأكدا مما إذا كان التحرك للنظر هو النهج الصحيح، فعلت ذلك بطريقة مختلفة، تغيير حجم UISCrollView. شرحت ذلك في التفاصيل على القليل مقالة - سلعة

للعودة إلى حالة العرض الأصلية، أضف:

-(void)textFieldDidEndEditing:(UITextField *)sender

{
    //move the main view, so that the keyboard does not hide it.
    if  (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

جرب هذه الخدعة القصيرة.

- (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 = textField.frame.origin.y / 2; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

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

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

هناك العديد من الحلول، لكنني أقضي بعض الساعات قبل بدء تشغيلها. لذلك، أضع هذا الرمز هنا (فقط لصق المشروع، أي تعديلات لا تحتاج):

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
    UITextField* activeField;
    UIScrollView *scrollView;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

    //scrool view must be under main view - swap it
    UIView* natView = self.view;
    [self setView:scrollView];
    [self.view addSubview:natView];

    CGSize scrollViewContentSize = self.view.frame.size;
    [scrollView setContentSize:scrollViewContentSize];

    [self registerForKeyboardNotifications];
}

- (void)viewDidUnload {
    activeField = nil;
    scrollView = nil;
    [self unregisterForKeyboardNotifications];
    [super viewDidUnload];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

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

}

-(void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}

- (void)keyboardWillShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect frame = self.view.frame;
    frame.size.height -= kbSize.height;
    CGPoint fOrigin = activeField.frame.origin;
    fOrigin.y -= scrollView.contentOffset.y;
    fOrigin.y += activeField.frame.size.height;
    if (!CGRectContainsPoint(frame, fOrigin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y + activeField.frame.size.height - frame.size.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
     [scrollView setContentOffset:CGPointZero animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    activeField = nil;
}

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

ملاحظة: آمل أن يساعد الرمز شخص ما على تحقيق تأثير مرغوب فيه بسرعة. (xcode 4.5)

@ user271753.

للحصول على رأيك مرة أخرى إلى الإضافة الأصلية:

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

لا يتطلب عرض التمرير لتتمكن من نقل إطار العرض. يمكنك تغيير الإطار viewcontroller's عرض بحيث ينتقل العرض بأكمله إلى ما يكفي فقط لوضع حقل نص Firstresponder فوق لوحة المفاتيح. عندما ركضت في هذه المشكلة، قمت بإنشاء فرعية من UIViewController هذا يفعل هذا. يلاحظ لوحة المفاتيح أن تظهر إشعارا ويجد البحث الفرعي المستجيب الأول (إذا لزم الأمر)، يقوم بتحريك العرض الرئيسي إلى أعلى ما يكفي بحيث يكون المستجيب الأول أعلى لوحة المفاتيح. عندما تخفي لوحة المفاتيح، فإنه ينشط العرض مرة أخرى حيث كان ذلك.

لاستخدام هذه الفئة الفرعية تجعل تحكم عرض مخصص الخاص بك فئة فرعية من gmkeyboardvc. ويرث هذه الميزة (فقط تأكد من أن نفذت viewWillAppear و viewWillDisappear يجب عليهم الاتصال بك سوبر). الفصل في جيثب.

SWIFT 4. .

يمكنك التحرك بسهولة صعودا وهبوطا UITextField أو UIView مع UIKeyBoard مع Animation enter image description here

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!
    @IBOutlet var chatView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }

    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.origin.y - curFrame.origin.y
        print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.chatView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
        },completion: nil)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

هنا هو الحل الاختراق الذي جئت مع تخطيط محدد. يشبه هذا الحل محلول Matt Gallagher في هذا القسم إلى عرض. ما زلت جديدا في تطوير iPhone، وأنا لست على دراية بكيفية عمل التخطيطات. وهكذا، هذا الاختراق.

يتعين على تطبيقي لدعم التمرير عند النقر في حقل، وكذلك التمرير عند تحديد المستخدم التالي على لوحة المفاتيح.

كان لدي uiview مع ارتفاع 775. وتنتشر الضوابط بشكل أساسي في مجموعات من 3 على مساحة كبيرة. انتهى بي الأمر مع تخطيط IB التالي.

UIView -> UIScrollView -> [UI Components]

هنا يأتي الاختراق

قمت بتعيين ارتفاع UISCrollView إلى 500 وحدة أكبر ثم التصميم الفعلي (1250). بعد ذلك، أنشأت مجموعة مع المناصب المطلقة التي أحتاج إلى التمرير إليها، وظيفة بسيطة للحصول عليها بناء على رقم علامة IB.

static NSInteger stepRange[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410
};

NSInteger getScrollPos(NSInteger i) {
    if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) {
        return 0 ;
    return stepRange[i] ;
}

الآن كل ما عليك فعله هو استخدام سطرين الكود التاليين في TextFieldDididBeginititibe و TextFieldShouldReturn (آخر واحد إذا كنت تقوم بإنشاء الملاحة الحقل التالية)

CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;

مثال.

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
    [self.scrollView setContentOffset:point animated:YES] ;
}


- (BOOL)textFieldShouldReturn:(UITextField *)textField {

    NSInteger nextTag = textField.tag + 1;
    UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];

    if (nextResponder) {
        [nextResponder becomeFirstResponder];
        CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ;
        [self.scrollView setContentOffset:point animated:YES] ;
    }
    else{
        [textField resignFirstResponder];
    }

    return YES ;
}

هذه الطريقة لا "التمرير مرة أخرى" لأن الأساليب الأخرى تفعل. لم يكن هذا شرطا. مرة أخرى كان هذا بالنسبة لأيفيو "طويل القامة" إلى حد ما، ولم يكن لدي أيام لتعلم محركات التصميم الداخلي.

حسب المستندات, ، اعتبارا من iOS 3.0، UITableViewController يقوم Class تلقائيا بتغيير حجم وإعادة تحديد عرض الجدول الخاص به عندما يكون هناك تحرير في خط الحقول النصية. أعتقد أنه غير كاف لوضع حقل النص داخل UITableViewCell كما أشار البعض.

من عند المستندات:

تدعم وحدة تحكم عرض الجدول التحرير المضمنة من صفوف عرض الجدول؛ على سبيل المثال، على سبيل المثال، قامت الصفوف بتدمير حقول نصية في وضع التحرير، فهي تمرير الصف الذي يتم تحريره أعلى لوحة المفاتيح الافتراضية التي يتم عرضها.

هنا لقد وجدت أبسط حل للتعامل مع لوحة المفاتيح.

تحتاج فقط إلى نسخ المعبأة أسفل رمز العينة وتغيير TextField أو أي طريقة عرض تريد التحرك لأعلى.

الخطوة 1

مجرد نسخ لصق أسفل طريقتين في وحدة تحكم

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void)deregisterFromKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

الخطوة 2

تسجيل وإخطارات لوحة المفاتيح Deregister في Viewwillappear. و ViewwilldisAppear. الأساليب على التوالي.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self registerForKeyboardNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [self deregisterFromKeyboardNotifications];
    [super viewWillDisappear:animated];
}

الخطوه 3

هنا يأتي جزء الروح، ما عليك سوى استبدال TextField الخاص بك، وتغيير الارتفاع إلى أي مدى تريد نقل الاتجاه الصعودي.

- (void)keyboardWasShown:(NSNotification *)notification
{
    NSDictionary* info = [notification userInfo];
    CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //you need replace your textfield instance here
    CGPoint textFieldOrigin = self.tokenForPlaceField.frame.origin;
    CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;

    CGRect visibleRect = self.view.frame;
    visibleRect.size.height -= currentKeyboardSize.height;

    if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
    {
        //you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below

        CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height  + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
        [self.scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification *)notification
{
    [self.scrollView setContentOffset:CGPointZero animated:YES];
}

المرجعي: نحن سوف، يرجى نقدر هذا الرجل, ، الذي شارك هذا الكود الجميل SNIP، حل نظيف.

آمل أن يكون هذا سوى شخص مفيد هناك.

تم البحث عن برنامج تعليمي جيد للمبتدئين حول هذا الموضوع، وجدت أفضل تعليمي هنا.

في ال MIScrollView.h مثال في أسفل البرنامج التعليمي تأكد من وضع مساحة في

@property (nonatomic, retain) id backgroundTapDelegate;

كما ترى.

متى UITextField هو في UITableViewCell يجب أن يكون التمرير الإعداد تلقائيا.

إذا لم يكن الأمر كذلك بسبب وجود رمز / إعداد غير صحيح من الجدول ".

على سبيل المثال عندما اخترت طاولتي الطويلة مع واحد UITextField في الأسفل على النحو التالي،

-(void) viewWillAppear:(BOOL)animated
{
   [self.tableview reloadData];
}

ثم تم حجب TextField في أسفل لوحة المفاتيح التي ظهرت عند النقر عليها داخل TextField.

لإصلاح هذا اضطررت للقيام بذلك -

-(void) viewWillAppear:(BOOL)animated
{
    //add the following line to fix issue
    [super viewWillAppear:animated];
    [self.tableview reloadData];
}

استخدم هذا الطرف الثالث الذي لا تحتاج إلى كتابة سطر واحد

https://github.com/hackiftekhar/iqkeyagleager.

قم بتنزيل المشروع واسحب وإسقاط IQKeyboardManager في مشروعك. إذا وجدت أي مشكلة، يرجى قراءة مستند README.

الرجال حقا حقا إزالة الصداع لإدارة لوحة المفاتيح ..

شكرا لك وحظا سعيدا!

ملحوظة: تفترض هذه الإجابة أن TextField الخاص بك في تسجيل الدخول.

أفضل التعامل مع هذا باستخدام SCROLLCONTENTENSET و SCROLLCONTENTOFFSET بدلا من العبث بإطارات رأيي.

أولا دعونا نستمع لإشعارات لوحة المفاتيح

//call this from viewWillAppear
-(void)addKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}
//call this from viewWillDisappear
-(void)removeKeyboardNotifications{
    [[NSNotificationCenter default
    Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

والخطوة التالية هي الاحتفاظ بممتلكات تمثل المستجيب الأول الحالي (UITEXTFIELD / UITEXTVIEW حاليا لوحة المفاتيح حاليا).

نحن نستخدم طرق المندوب لتعيين هذه الخاصية. إذا كنت تستخدم مكونا آخر، فستحتاج إلى شيء مشابه.

لاحظ أنه بالنسبة إلى TextField، حددناها في DEDBEGINDITING ولل وذلك لأن TextViewDIdBeginititititibe يطلق عليه بعد uikeyboardwillshownotification لسبب ما.

-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{
    self.currentFirstResponder = textView;
    return YES;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField{
    self.currentFirstResponder = textField;
}

أخيرا، إليك السحر

- (void)keyboardWillShow:(NSNotification*)aNotification{
    NSDictionary* info = [aNotification userInfo];
    CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];


    /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/
    if(self.currentFirstResponder){

        //keyboard origin in currentFirstResponderFrame
        CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.origin fromView:nil];

        float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y);

        //only scroll the scrollview if keyboard overlays the first responder
        if(spaceBetweenFirstResponderAndKeyboard>0){
            //if i call setContentOffset:animate:YES it behaves differently, not sure why
            [UIView animateWithDuration:0.25 animations:^{
                [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)];
            }];
        }
    }

    //set bottom inset to the keyboard height so you can still scroll the whole content

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0);
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;

}

- (void)keyboardWillHide:(NSNotification*)aNotification{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}

هذا هو الحل باستخدام SWIFT.

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size

        let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;

        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your app might not need or want this behavior.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top