iphone - type - xcode輸入框




UITextField:鍵盤出現時移動視圖 (4)

我得到你的問題只是簡單的事情只是給UIScrollview插座。 為視圖中的每個文本字段設置唯一的Tag屬性。

-(void)textFieldDidBeginEditing:(UITextField *)textField
    {   
        switch (textField.tag)
        {
            case 2:    //can be your textfiled tag
              { CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-150); 
                                           //set figure y-150 as per your comfirt
                  [scrollview setContentOffset:scrollPoint animated:YES]; 
             }break;

              case 3:   
              { CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-180); 
                                           //set figure y-180 as per your comfirt
                  [scrollview setContentOffset:scrollPoint animated:YES]; 
             }break;

             ...

         }
    }

    -(void)textFieldDidEndEditing:(UITextField *)textField{

        if(textField.tag==3){
            [scrollview setContentOffset:CGPointZero animated:YES];
                }
         //set the last textfield when you want to disappear keyboard.
    }

我目前正在開發一個帶有單一視圖的iPhone應用程序,它有多個UITextField用於輸入。 鍵盤顯示時,它覆蓋底部文本字段。 所以我添加了相應的textFieldDidBeginEditing:方法,以便向上移動視圖,效果很好:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    if ( ( textField != inputAmount ) && ( textField != inputAge ) ) {
        NSTimeInterval animationDuration = 0.300000011920929;
        CGRect frame = self.view.frame;
        frame.origin.y -= kOFFSET_FOR_KEYBOARD;
        frame.size.height += kOFFSET_FOR_KEYBOARD;
        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
        [UIView setAnimationDuration:animationDuration];
        self.view.frame = frame;
        [UIView commitAnimations];      
    }
}

如果消息源是鍵盤顯示時可見的文本字段之一,則此方法檢查,如果不是,則向上移動視圖。

我還添加了textFieldDidEndEnditing:方法,它再次向下移動視圖(並根據更改的輸入更新一些模型對象):

- (void)textFieldDidEndEditing:(UITextField *)textField {
    if ( ( textField != inputMenge ) && ( textField != inputAlter ) ) {
        NSTimeInterval animationDuration = 0.300000011920929;
        CGRect frame = self.view.frame;
        frame.origin.y += kOFFSET_FOR_KEYBOARD;
        frame.size.height -= kOFFSET_FOR_KEYBOARD;
        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
        [UIView setAnimationDuration:animationDuration];
        self.view.frame = frame;
        [UIView commitAnimations];      
    }
    // Additional Code
}

但是,這個解決方案有一個簡單的缺陷:當我完成編輯其中一個“隱藏​​”文本字段並觸摸另一個文本字段時,鍵盤消失,視圖向下移動,視圖再次向上移動,鍵盤重新出現。

是否有可能使鍵盤在兩個編輯(“隱藏”文本字段)之間消失和重新出現 - 以便只有當所選文本字段從鍵盤隱藏的文本字段更改為不會隱藏的文本字段時,視圖才會移動)?


相當簡單的解決方案,適用於所有屏幕尺寸

首先,您必須將UITextFields嵌入到UIScrollView中。 在我的例子中,我有幾個UITextFields和一個UITextView。

然後你必須繼承UITextFieldDelegate,UITextViewDelegate。

class SettingsVC: UIViewController, UITextFieldDelegate, UITextViewDelegate

將textfield和textview的委託分配給self。

fullNameTextField.delegate = self usernameTextField.delegate = self websiteTextField.delegate = self profileDescription.delegate = self

然後使用此代碼:

var editingTextInput: UIView!


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.keyboardShown(notification:)),
                                           name: NSNotification.Name.UIKeyboardDidShow,
                                           object: nil)
    

  }
  
    override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
  }
  
  func keyboardShown(notification: NSNotification) {
    
    if let infoKey  = notification.userInfo?[UIKeyboardFrameEndUserInfoKey],
      let rawFrame = (infoKey as AnyObject).cgRectValue {
      
      let keyboardFrame = view.convert(rawFrame, to: view)
      let editingTextInputFrame = self.editingTextInput.convert(self.editingTextInput.frame, to: view)

      
      if editingTextInputFrame.maxY > keyboardFrame.minY{
        
        let diff = keyboardFrame.minY - editingTextInputFrame.maxY
        containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
        
      }
    }
  }
  
  func textFieldDidBeginEditing(_ textField: UITextField) {
    self.editingTextInput = textField
  }
  
  func textViewDidBeginEditing(_ textView: UITextView) {
    self.editingTextInput = textView
  }
  
  func textFieldDidEndEditing(_ textField: UITextField) {
    containerScrollView.setContentOffset(CGPoint.zero, animated: true)
  }
  
  func textViewDidEndEditing(_ textView: UITextView) {
    containerScrollView.setContentOffset(CGPoint.zero, animated: true)
  }

簡而言之,您訂閱了UIKeyboardDidShow通知。 當您點擊textField或顯示textView鍵盤時,您可以輕觸鍵盤的框架和輸入元素框架。 將它們轉換為viewController的坐標系,並將輸入元素的最低點與鍵盤的最高點進行比較。 如果element的下半部分低於鍵盤的最高部分,則將containerScrollView的偏移設置為它們之間的差異。

if editingTextInputFrame.maxY > keyboardFrame.minY{
            
            let diff = keyboardFrame.minY - editingTextInputFrame.maxY
            containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
            
          }


此視圖控制器必須是UITextView Delegate,您必須在viewdidload設置self.textview.delegate = self

 -(void) textViewDidBeginEditing:(UITextView *)textView
    {
        NSLog(@"%f",self.view.frame.origin.y);
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.25f];
        CGRect frame = self.view.frame;
        frame.origin.y =frame.origin.y -204;
        [self.view setFrame:frame];
        [UIView commitAnimations];
    }

-(void) textViewDidEndEditing:(UITextView *)textView
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.25f];
    CGRect frame = self.view.frame;
    frame.origin.y = frame.origin.y + 204;
    [self.view setFrame:frame];
    [UIView commitAnimations];
}

此解決方案基於ComSubVie的解決方案。

優點:

  • 它支持設備旋轉 - 適用於所有方向;
  • 它不會對動畫持續時間和曲線的值進行硬編碼,而是從鍵盤通知中讀取它們;
  • 它利用UIKeyboardWillShowNotification而不是UIKeyboardDidShowNotification來同步鍵盤動畫和自定義動作;
  • 它不使用已棄用的UIKeyboardBoundsUserInfoKey ;
  • 由於按下國際鍵,它處理鍵盤調整大小;
  • 通過取消註冊鍵盤事件來修復內存洩漏;
  • 所有鍵盤處理代碼都封裝在一個單獨的類中 - KBKeyboardHandler ;
  • 靈活性 - KBKeyboardHandler類可以輕鬆擴展/修改,以更好地滿足特定需求;

限制:

  • 適用於iOS 4及更高版本,需要進行少量修改才能支持舊版本;
  • 它適用於具有單個UIWindow應用程序。 如果您使用多個UIWindows,則可能需要修改retrieveFrameFromNotification:方法。

用法:

在項目中包含KBKeyboardHandler.h,KBKeyboardHandler.m和KBKeyboardHandlerDelegate.h。 在視圖控制器中實現KBKeyboardHandlerDelegate協議 - 它由單個方法組成,當鍵盤顯示,隱藏或其大小發生變化時,將調用該方法。 實例化KBKeyboardHandler並設置其委託(通常為self)。 請參閱下面的示例MyViewController

KBKeyboardHandler.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@protocol KBKeyboardHandlerDelegate;

@interface KBKeyboardHandler : NSObject

- (id)init;

// Put 'weak' instead of 'assign' if you use ARC
@property(nonatomic, assign) id<KBKeyboardHandlerDelegate> delegate; 
@property(nonatomic) CGRect frame;

@end

KBKeyboardHandler.m

#import "KBKeyboardHandler.h"
#import "KBKeyboardHandlerDelegate.h"

@implementation KBKeyboardHandler

- (id)init
{
    self = [super init];
    if (self)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];

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

    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

@synthesize delegate;
@synthesize frame;

- (void)keyboardWillShow:(NSNotification *)notification
{
    CGRect oldFrame = self.frame;    
    [self retrieveFrameFromNotification:notification];

    if (oldFrame.size.height != self.frame.size.height)
    {
        CGSize delta = CGSizeMake(self.frame.size.width - oldFrame.size.width,
                                  self.frame.size.height - oldFrame.size.height);
        if (self.delegate)
            [self notifySizeChanged:delta notification:notification];
    }
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    if (self.frame.size.height > 0.0)
    {
        [self retrieveFrameFromNotification:notification];
        CGSize delta = CGSizeMake(-self.frame.size.width, -self.frame.size.height);

        if (self.delegate)
            [self notifySizeChanged:delta notification:notification];
    }

    self.frame = CGRectZero;
}

- (void)retrieveFrameFromNotification:(NSNotification *)notification
{
    CGRect keyboardRect;
    [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
    self.frame = [[UIApplication sharedApplication].keyWindow.rootViewController.view convertRect:keyboardRect fromView:nil];
}

- (void)notifySizeChanged:(CGSize)delta notification:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];

    UIViewAnimationOptions curve;
    [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];

    NSTimeInterval duration;
    [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];

    void (^action)(void) = ^{
        [self.delegate keyboardSizeChanged:delta];
    };

    [UIView animateWithDuration:duration
                          delay:0.0
                        options:curve
                     animations:action
                     completion:nil];    
}

@end

KBKeyboardHandlerDelegate.h

@protocol KBKeyboardHandlerDelegate

- (void)keyboardSizeChanged:(CGSize)delta;

@end

示例MyViewController.h

@interface MyViewController : UIViewController<KBKeyboardHandlerDelegate>
...
@end

示例MyViewController.m

@implementation MyViewController
{
    KBKeyboardHandler *keyboard;
}

- (void)dealloc
{
    keyboard.delegate = nil;
    [keyboard release];
    [super dealloc];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    keyboard = [[KBKeyboardHandler alloc] init];
    keyboard.delegate = self;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    keyboard.delegate = nil;
    [keyboard release];
    keyboard = nil;
}

- (void)keyboardSizeChanged:(CGSize)delta
{
    // Resize / reposition your views here. All actions performed here 
    // will appear animated.
    // delta is the difference between the previous size of the keyboard 
    // and the new one.
    // For instance when the keyboard is shown, 
    // delta may has width=768, height=264,
    // when the keyboard is hidden: width=-768, height=-264.
    // Use keyboard.frame.size to get the real keyboard size.

    // Sample:
    CGRect frame = self.view.frame;
    frame.size.height -= delta.height;
    self.view.frame = frame;
}

更新:修復了iOS 7警告,感謝@weienv。





uitextfield