iphone - UITextField: कुंजीपटल दिखाई देने पर दृश्य देखें




objective-c cocoa-touch (4)

मुझे आपकी समस्या मिली है बस यूआईएसक्रॉलव्यू को आउटलेट दें। प्रत्येक टेक्स्टफील्ड को देखने के लिए अद्वितीय टैग संपत्ति सेट करें।

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

मैं वर्तमान में एक आईफोन एप्लिकेशन पर एक दृश्य के साथ काम कर रहा हूं, जिसमें इनपुट के लिए कई यूआईटीएक्स्टफिल्ड्स हैं। जब कीबोर्ड दिखाता है, तो यह नीचे टेक्स्टफील्ड को ओवरले करता है। तो मैंने दृश्य को स्थानांतरित करने के लिए संबंधित 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: भी जोड़ा 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

स्वयं को टेक्स्टफील्ड और टेक्स्टव्यू के प्रतिनिधियों को असाइन करें।

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 अधिसूचना की सदस्यता लेते हैं। जब आप टेक्स्ट फ़ील्ड या टेक्स्ट व्यू कीबोर्ड पर टैप करते हैं तो दिखाया जाता है और आप कुंजीपटल के फ्रेम और इनपुट तत्व के फ्रेम को पकड़ते हैं जिसे आपने टैप किया है। उन्हें नियंत्रक की समन्वय प्रणाली देखने के लिए कनवर्ट करें और कीबोर्ड के उच्चतम इनपुट इनपुट तत्व की तुलना करें। यदि तत्व के निचले भाग को कीबोर्ड के उच्चतम से कम है, तो कंटेनर सेट ऑफसेट के सेट के बजाय उनके बीच के अंतर के लिए।

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


यह दृश्य नियंत्रक UITextView प्रतिनिधि होना चाहिए और आपको viewdidload self.textview.delegate = self को viewdidload में सेट करना होगा

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

यह समाधान कॉमसुबी के एक पर आधारित है।

लाभ:

  • यह डिवाइस रोटेशन का समर्थन करता है - सभी उन्मुखताओं के लिए काम करता है;
  • यह एनीमेशन अवधि और वक्र के मानों को हार्डकोड नहीं करता है, यह उन्हें कीबोर्ड अधिसूचना से पढ़ता है;
  • यह कीबोर्ड एनीमेशन और कस्टम क्रियाओं को सिंक करने के लिए UIKeyboardWillShowNotification बजाय UIKeyboardWillShowNotification का उपयोग करता है;
  • यह बहिष्कृत UIKeyboardBoundsUserInfoKey उपयोग नहीं करता है;
  • यह अंतरराष्ट्रीय कुंजी दबाए जाने के कारण कीबोर्ड आकार बदलता है;
  • कीबोर्ड घटनाओं के लिए पंजीकरण रद्द करके निश्चित स्मृति रिसाव;
  • सभी कीबोर्ड हैंडलिंग कोड एक अलग वर्ग में encapsulated है - KBKeyboardHandler ;
  • लचीलापन - KBKeyboardHandler वर्ग को विशिष्ट आवश्यकताओं के अनुरूप बेहतर विस्तार / संशोधित किया जा सकता है;

सीमाएं:

  • आईओएस 4 और उसके बाद के संस्करणों के लिए काम करता है, पुराने संस्करणों का समर्थन करने के लिए इसे छोटे बदलावों की आवश्यकता होती है;
  • यह एक UIWindow साथ अनुप्रयोगों के लिए काम करता है। यदि आप एकाधिक UIWindows का उपयोग करते हैं, तो आपको retrieveFrameFromNotification: फ़्रेम फ़्रेम नोटिफिकेशन retrieveFrameFromNotification: विधि को संशोधित retrieveFrameFromNotification: आवश्यकता हो सकती है।

उपयोग:

अपनी परियोजना में KBKeyboardHandler.h, KBKeyboardHandler.m और KBKeyboardHandlerDelegate.h शामिल करें। अपने व्यू कंट्रोलर में KBKeyboardHandlerDelegate प्रोटोकॉल को कार्यान्वित करें - इसमें एक विधि होती है, जिसे कीबोर्ड दिखाया जाता है, छुपाया जाता है या उसका आकार बदल जाता है। KBKeyboardHandler को KBKeyboardHandler और इसके प्रतिनिधि (आमतौर पर स्वयं) सेट करें। नीचे नमूना 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;
}

अद्यतन: फिक्स्ड आईओएस 7 चेतावनी, धन्यवाद @weienv।





uitextfield