ios中鍵盤處理源碼

 

1:先分別設置各個文本框的鍵盤類型(inputview)-->在特定鍵盤中textediting中禁用輸入。緩存

 
 


2:而後遞歸綁定各個鍵盤的工具條(inputaccessview).
而且個各個控件綁定有順序的tagide

 
 

3:上一個和下一個功能:先找到第一響應者,而後利用tag進行切換第一響應者。
注意點(
1:當前tag等於最小tag,工具條的上一個禁掉--》在循環中
2:當前編輯的時候,判斷tag和最小tag進行判斷,是否禁用上一個--》在文本框代理中
工具



//
MJScrollView.m // 動畫和事件綜合例子-鍵盤處理 // // Created by mj on 13-4-15. // Copyright (c) 2013年 itcast. All rights reserved. // #import "MJScrollView.h" #import "UIView+Add.h" @interface MJScrollView () { CGPoint _lastOffset; } @end @implementation MJScrollView #pragma mark - 生命週期方法 - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initial]; } return self; } - (id)init { if (self = [super init]) { [self initial]; } return self; } #pragma mark 當MJScrollView從xib中建立完畢後會調用這個方法 - (void)awakeFromNib { [self initial]; } - (void)dealloc { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 注意:記得要移除 [center removeObserver:self]; [super dealloc]; } #pragma mark 初始化 - (void)initial { self.contentSize = self.bounds.size; NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 註冊鍵盤顯示的通知 [center addObserver:self selector:@selector(keybordWillShow:) name:UIKeyboardWillShowNotification object:nil]; // 註冊鍵盤隱藏的通知 [center addObserver:self selector:@selector(keybordWillHide:) name:UIKeyboardWillHideNotification object:nil]; } #pragma mark 鍵盤顯示出來的時候調用 - (void)keybordWillShow:(NSNotification *)notification{ //NSLog(@"keybordWillShow,%@", notification); CGRect keyboardRect = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; UITextField *textField = [UIView findFistResponder:self]; // toView用nil值,表明UIWindow CGRect convertRect = [textField convertRect:textField.bounds toView:nil]; CGFloat distance = keyboardRect.origin.y - (convertRect.origin.y + convertRect.size.height + 10); if (distance < 0) { // 說明鍵盤擋住了文本框 [self animationWithUserInfo:notification.userInfo block:^{ CGPoint offset = _lastOffset = self.contentOffset; offset.y -= distance; self.contentOffset = offset; }]; } } #pragma mark 鍵盤隱藏的時候調用 - (void)keybordWillHide:(NSNotification *)notification { [self animationWithUserInfo:notification.userInfo block:^{ self.contentOffset = _lastOffset; }]; } #pragma mark 抽出一個方法來執行動畫 - (void)animationWithUserInfo:(NSDictionary *)userInfo block:(void (^)(void))block { // 取出鍵盤彈出的時間 CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; // 取出鍵盤彈出的速率節奏 int curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:duration]; [UIView setAnimationCurve:curve]; // 調用block block(); [UIView commitAnimations]; } #pragma mark 監聽scrollview點擊 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // 退出鍵盤 [self endEditing:YES]; } @end
@implementation UIView (Add)
#pragma mark 遞歸找出第一響應者
+ (UITextField *)findFistResponder:(UIView *)view {
    for (UIView *child in view.subviews) {
        if ([child respondsToSelector:@selector(isFirstResponder)]
            &&
            [child isFirstResponder]) {
            return (UITextField *)child;
        }
        
        UITextField *field = [self findFistResponder:child];
        if (field) {
            return field;
        }
    }
    
    return nil;
}
@end

//
//  MJViewController.m
//  動畫和事件綜合例子-鍵盤處理
//
//  Created by mj on 13-4-15.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import "MJViewController.h"
#import "KeyboardTool.h"
#import "UIView+Add.h"

// 文本框最小的tag
#define kTextFieldMinTag 10

@interface MJViewController () {
    KeyboardTool *_tool;
    // 文本框的總數
    int _textFieldCount;
}
@end

@implementation MJViewController

#pragma mark - 生命週期方法
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 初始化生日文本框
    [self initBirthday];
    
    // 初始化性別文本框
    [self initSex];
    
    // 給全部的文本框綁定KeyboardTool
    KeyboardTool *tool = [KeyboardTool keyboardTool];
    tool.delegate = self;
    [self initKeyboardTool:tool view:self.view];
    _tool = tool;
}

#pragma mark - KeyboardTool代理方法
- (void)keyboardTool:(KeyboardTool *)tool buttonClick:(KeyboardToolButtonType)type {
    // case裏面有多行時,寫個{}
    
    // 完成
    if (type == kKeyboardToolButtonTypeDone) {
        [self.view endEditing:YES];
    } else { // 下一個 或者 上一個
        
        // 獲取當前的第一響應者
        UITextField *responder = [UIView findFistResponder:self.view];
        
        // 取出新的響應者
        int tag = responder.tag;
        
        type == kKeyboardToolButtonTypeNext ? tag++ : tag --;
    
        
        UITextField *newResponder = (UITextField *)[self.view viewWithTag:tag];
        
        // 讓newResponder稱爲第一響應者
        [newResponder becomeFirstResponder];
        
        // 判斷是否是最上面的文本框了
        tool.previousBtn.enabled = tag != kTextFieldMinTag;
        
        // 判斷是否是最下面的文本框了
        int maxTag = kTextFieldMinTag + _textFieldCount -1;
        tool.nextBtn.enabled = tag != maxTag;
        
//        if (tag == kTextFieldMinTag) {
//            tool.previousBtn.enabled = NO;
//        } else {
//            tool.previousBtn.enabled = YES;
//        }
    }
}

#pragma mar - 給全部的文本框綁定KeyboardTool
- (void)initKeyboardTool:(KeyboardTool *)tool view:(UIView *)view {
    
    // static不能省略
    //static int i = 0;
    
    for (UITextField *child in view.subviews) {
        if ([child isKindOfClass:[UITextField class]]) {
            child.inputAccessoryView = tool;
            // 綁定tag
            child.tag = kTextFieldMinTag + _textFieldCount;
            
            // 設置文本框的代理
            child.delegate = self;
            
            // 設置文本框的返回鍵類型
            child.returnKeyType = UIReturnKeyDone;
            
            _textFieldCount ++;
            
            NSLog(@"%@-tag=%i", NSStringFromClass([view class]), child.tag);
        } else { // 搜索裏面的文本框
            [self initKeyboardTool:tool view:child];
        }
    }
}

#pragma mark - 生日
#pragma mark 初始化生日文本框
- (void)initBirthday {
    // 初始化一個日期選擇控件(不用指定寬高)
    UIDatePicker *picker = [[[UIDatePicker alloc] init] autorelease];
    
    // 設置顯示中文
    picker.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"] autorelease];
    // 只顯示年月日
    picker.datePickerMode = UIDatePickerModeDate;
    // 添加值改變的監聽器
    [picker addTarget:self action:@selector(birthdayChange:) forControlEvents:UIControlEventValueChanged];
    self.birthday.inputView = picker;
    
    //self.birthday.delegate = self;
}

#pragma mark 監聽日期選擇控件的改變
- (void)birthdayChange:(UIDatePicker *)picker {
    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
    formatter.dateFormat = @"yyyy-MM-dd";
    self.birthday.text = [formatter stringFromDate:picker.date];
}
#pragma mark - UITextField代理方法
#pragma mark 返回NO表明不容許手動改變文本框的文本
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // 只有生日和性別纔不容許修改文字
    return !(textField == self.birthday || textField == self.sex);
}
#pragma mark 文本框開始編輯(開始聚焦)
- (void)textFieldDidBeginEditing:(UITextField *)textField {
    // 判斷是否是最上面的文本框了
    _tool.previousBtn.enabled = textField.tag != kTextFieldMinTag;
    
    // 判斷是否是最下面的文本框了
    int maxTag = kTextFieldMinTag + _textFieldCount -1;
    _tool.nextBtn.enabled = textField.tag != maxTag;
}
#pragma mark 點擊了Return按鈕
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [self.view endEditing:YES];
    return YES;
}

#pragma mark - 性別
#pragma mark 初始化性別文本框
- (void)initSex {
    UIPickerView *picker = [[[UIPickerView alloc] init] autorelease];
    // 設置數據源
    picker.dataSource = self;
    // 設置代理
    picker.delegate = self;
    // 明顯地顯示選中了哪一行
    picker.showsSelectionIndicator = YES;
    
    self.sex.inputView = picker;
    
    //self.sex.delegate = self;
}
#pragma mark - UIPickerView數據源方法
#pragma mark 一共有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 1;
}
#pragma mark 第component列有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    return 2;
}

#pragma mark - UIPickerView代理方法
// picker的每一行要保證結構是同樣
// reusingView:(UIView *)view就是緩存池中的可循環利用的View
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
    
    static int iconTag = 10;
    static int labelTag = 20;
    
    // 若是沒有可循環利用的View
    if (view == nil) {
        view = [[[UIView alloc] init] autorelease];
        CGFloat viewHeight = 50;
        view.bounds = CGRectMake(0, 0, 100, viewHeight);
        
        // 添加ImageView
        UIImageView *icon = [[[UIImageView alloc] init] autorelease];
        CGFloat iconX = 5;
        CGFloat iconWidth = 32;
        CGFloat iconHeight = 32;
        CGFloat iconY = (viewHeight - iconHeight) * 0.5f;
        icon.frame = CGRectMake(iconX, iconY, iconWidth, iconHeight);
        icon.tag = iconTag;
        [view addSubview:icon];
        
        // 添加文本
        UILabel *label = [[[UILabel alloc] init] autorelease];
        label.frame = CGRectMake(iconX + iconWidth + 15, 0, 60, viewHeight);
        label.backgroundColor = [UIColor clearColor];
        label.tag = labelTag;
        [view addSubview:label];
    }
    
    // 設置圖標
    UIImageView *icon = (UIImageView *)[view viewWithTag:iconTag];
    icon.image = [UIImage imageNamed:row==0?@"male.png":@"female.png"];
    
    // 設置文字
    UILabel *label = (UILabel *)[view viewWithTag:labelTag];
    label.text = row==0?@"":@"";
    
    return view;
}
#pragma mark 監聽選中了某一行
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    self.sex.text = row==0?@"":@"";
}
@end
#import <UIKit/UIKit.h>
@protocol KeyboardToolDelegate;

typedef enum {
    kKeyboardToolButtonTypeNext, // 下一個按鈕
    kKeyboardToolButtonTypePrevious, // 上一個按鈕
    kKeyboardToolButtonTypeDone // 完成按鈕
} KeyboardToolButtonType;

@interface KeyboardTool : UIToolbar
// 按鈕
@property (nonatomic, readonly) IBOutlet UIBarButtonItem *nextBtn;
@property (nonatomic, readonly) IBOutlet UIBarButtonItem *previousBtn;
@property (nonatomic, readonly) IBOutlet UIBarButtonItem *doneBtn;

// 代理通常用assign策略
@property (nonatomic, assign) id<KeyboardToolDelegate> delegate;

+ (id)keyboardTool;

// 這裏寫成 - 是爲了能在xib中連線
- (IBAction)next;
- (IBAction)previous;
- (IBAction)done;
@end

@protocol KeyboardToolDelegate <NSObject>
- (void)keyboardTool:(KeyboardTool *)tool buttonClick:(KeyboardToolButtonType)type;
@end


#import "KeyboardTool.h"

@implementation KeyboardTool

@synthesize delegate = _toolDelegate;

#pragma mark 從xib文件中初始化一個KeyboardTool
+ (id)keyboardTool {
    // owner能夠傳KeyboardTool這個類
    // 點擊"下一個"按鈕的時候,要調用owner的next方法
    
    NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"keyboardTool" owner:nil options:nil];
    
    // 返回初始化完畢的KeyboardTool
    return [array lastObject];
}

#pragma mark - 按鈕點擊
- (void)next {
    if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonClick:)]) {
        [_toolDelegate keyboardTool:self buttonClick:kKeyboardToolButtonTypeNext];
    }
}

- (void)previous {
    if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonClick:)]) {
        [_toolDelegate keyboardTool:self buttonClick:kKeyboardToolButtonTypePrevious];
    }
}

- (void)done {
    if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonClick:)]) {
        [_toolDelegate keyboardTool:self buttonClick:kKeyboardToolButtonTypeDone];
    }
}
@end
相關文章
相關標籤/搜索