iOS开发之UI篇(8)—— UITextField

版本
Xcode 9.1

基本用法

继承关系:

UITextField : UIControl : UIView : UIResponder : NSObject

示例:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    /* ----- 初始化 ----- */
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 100, 300, 30)];
    textField.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, 100);     // 居中
    [self.view addSubview:textField];   // 添加至self.view
    
    /* ----- 常用属性 ----- */

    // 设置背景颜色
    textField.backgroundColor = [UIColor whiteColor];
    textField.layer.cornerRadius = 10;
    
    // 设置文字内容
    textField.text = @"看影成痴";
    // 设置字体颜色
    textField.textColor = [UIColor purpleColor];
    // 设置字体样式及大小
    textField.font = [UIFont systemFontOfSize:18.0];
    // 设置对齐方式
    textField.textAlignment = NSTextAlignmentCenter;
    // 设置边框的样式(cornerRadius将无效)
    textField.borderStyle = UITextBorderStyleRoundedRect;
    // 设置提示文字
    textField.placeholder = @"请输入用户名";
    
    // 设置清空模式,是否每次编辑时都清空一下
    textField.clearsOnBeginEditing = YES;
    // 自动适应输入框宽度,让输入框可以显示输入的一定数量的所有字体
    textField.adjustsFontSizeToFitWidth = YES;
    // 设置文字显示的最小字体大小
    textField.minimumFontSize = 12;
    
    // 设置可用状态的背景图片(拉伸)
    textField.background = [UIImage imageNamed:@""];
    // 设置不可用状态的背景图片(拉伸)
    textField.disabledBackground = [UIImage imageNamed:@""];

    // 设置清理按钮模式
    textField.clearButtonMode = UITextFieldViewModeWhileEditing;
    // 设置输入框左图
    textField.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"left.png"]];
    textField.leftView.bounds = CGRectMake(0, 0, 30, 30);
    // 左图显示模式(编辑时不显示)
    textField.leftViewMode = UITextFieldViewModeUnlessEditing;
    // 设置输入框右图
    textField.rightView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"right.png"]];
    textField.rightView.bounds = CGRectMake(0, 0, 30, 30);
    // 右图显示模式
    textField.rightViewMode = UITextFieldViewModeUnlessEditing;
    
    // 是否密文输入(输入内容是否可见)
    textField.secureTextEntry = NO;
    // 设置键盘外观
    textField.keyboardAppearance = UIKeyboardAppearanceDark;
    // 设置键盘类型
    textField.keyboardType = UIKeyboardTypeNumberPad;
    // 设置返回键类型
    textField.returnKeyType = UIReturnKeyRoute;
    // 设置首字母是否大写
    textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
    // 是否自动修正输入内容
    textField.autocorrectionType = UITextAutocorrectionTypeDefault;
}

示例效果:

示例中的一些属性枚举:

/* 文字对齐方式 */
typedef NS_ENUM(NSInteger, NSTextAlignment) {
    NSTextAlignmentLeft      = 0,    // 左对齐
#if TARGET_OS_IPHONE                 // 判断真机or模拟器,我们只管枚举值对应的对齐方式即可
    NSTextAlignmentCenter    = 1,    // 居中(真机)
    NSTextAlignmentRight     = 2,    // 右对齐(真机)
#else /* !TARGET_OS_IPHONE */
    NSTextAlignmentRight     = 1,    // 右对齐(真机)
    NSTextAlignmentCenter    = 2,    // 居中(真机)
#endif
    NSTextAlignmentJustified = 3,    // 最后一行和段落对齐
    NSTextAlignmentNatural   = 4,    // 默认对齐脚本
} NS_ENUM_AVAILABLE_IOS(6_0);


/* 边框样式 */
typedef NS_ENUM(NSInteger, UITextBorderStyle) {
    UITextBorderStyleNone,           // 默认样式,无边框
    UITextBorderStyleLine,           // 边框加黑色线条
    UITextBorderStyleBezel,          // 边框加灰色线条,上边和左边加重
    UITextBorderStyleRoundedRect     // 圆角 
};


/* 某个属性(譬如删除按钮,leftView)出现时机 */
typedef NS_ENUM(NSInteger, UITextFieldViewMode) {
    UITextFieldViewModeNever,        // 从不出现
    UITextFieldViewModeWhileEditing, // 编辑时出现
    UITextFieldViewModeUnlessEditing,// 非编辑时出现
    UITextFieldViewModeAlways        // 总是出现
};


/* ----- 以下是与 输入内容or键盘 相关属性枚举 ----- */

/* 自动修正内容 */
typedef NS_ENUM(NSInteger, UITextAutocorrectionType) {
    UITextAutocorrectionTypeDefault, // 默认,可自动修正
    UITextAutocorrectionTypeNo,      // 不可修正
    UITextAutocorrectionTypeYes,     // 可自动修正
};


/* 首字母大写 */
typedef NS_ENUM(NSInteger, UITextAutocapitalizationType) {
    UITextAutocapitalizationTypeNone,          // 不自动大写
    UITextAutocapitalizationTypeWords,         // 单词首字母大写
    UITextAutocapitalizationTypeSentences,     // 句子首字母大写 
    UITextAutocapitalizationTypeAllCharacters, // 所有字母均大写
};


/* 键盘外观 */
typedef NS_ENUM(NSInteger, UIKeyboardAppearance) {
    UIKeyboardAppearanceDefault,          // 默认外观,浅灰色
    UIKeyboardAppearanceDark,             // 深灰色
    UIKeyboardAppearanceLight,            // 浅灰色
    UIKeyboardAppearanceAlert,            // 深灰色(已弃用)
};


/* 键盘类型 */
typedef NS_ENUM(NSInteger, UIKeyboardType) {
    UIKeyboardTypeDefault,                // 默认键盘,支持所有字符
    UIKeyboardTypeASCIICapable,           // ASCII类型
    UIKeyboardTypeNumbersAndPunctuation,  // 电话类型,支持+*#
    UIKeyboardTypeURL,                    // URL类型支持 . / .com
    UIKeyboardTypeNumberPad,              // A number pad with locale-appropriate digits (0-9, ۰-۹, ०-९, etc.). Suitable for PIN entry.
    UIKeyboardTypePhonePad,               // 电话类型 ,支持0-9, * , #
    UIKeyboardTypeNamePhonePad,           // 电话类型,支持输入人名
    UIKeyboardTypeEmailAddress,           // 电子邮件类型,支持空格 @ . 邮件地址
    UIKeyboardTypeDecimalPad,             // 数字键盘,支持小数点
    UIKeyboardTypeTwitter,                // 为twitter优化的键盘,更容易输入@ #
    UIKeyboardTypeWebSearch,              // 为URL优化的键盘,支持空格 . 地址
    UIKeyboardTypeASCIICapableNumberPad,  // 数字键盘,总是ASCII数字类型(iOS 10.0开始引入)
    UIKeyboardTypeAlphabet,               // 已弃用
};


/* 键盘的返回键类型 */
typedef NS_ENUM(NSInteger, UIReturnKeyType) {
    UIReturnKeyDefault,                   // 默认,标有Return的灰色按钮
    UIReturnKeyGo,                        // 标有Go的蓝色按钮
    UIReturnKeyGoogle,                    // 标有Google的蓝色按钮
    UIReturnKeyJoin,                      // 标有Join的蓝色按钮
    UIReturnKeyNext,                      // 标有Next的蓝色按钮
    UIReturnKeyRoute,                     // 标有Route的蓝色按钮
    UIReturnKeySearch,                    // 标有Search的蓝色按钮
    UIReturnKeySend,                      // 标有Send的蓝色按钮
    UIReturnKeyYahoo,                     // 标有Yahoo的蓝色按钮
    UIReturnKeyDone,                      // 标有Done的蓝色按钮
    UIReturnKeyEmergencyCall,             // 紧急呼叫按钮
    UIReturnKeyContinue ,                 // 标有Continue的灰色按钮(iOS9.0开始引入)
};

键盘类型图示:

  • UIKeyboardTypeDefault
UIKeyboardTypeDefault
  • UIKeyboardTypeASCIICapable
UIKeyboardTypeASCIICapable
  • UIKeyboardTypeNumbersAndPunctuation
UIKeyboardTypeNumbersAndPunctuation
  • UIKeyboardTypeURL
UIKeyboardTypeURL
  • UIKeyboardTypeNumberPad
UIKeyboardTypeNumberPad
  • UIKeyboardTypePhonePad
UIKeyboardTypePhonePad
  • UIKeyboardTypeNamePhonePad
UIKeyboardTypeNamePhonePad
  • UIKeyboardTypeEmailAddress
UIKeyboardTypeEmailAddress
  • UIKeyboardTypeDecimalPad
UIKeyboardTypeDecimalPad
  • UIKeyboardTypeTwitter
UIKeyboardTypeTwitter
  • UIKeyboardTypeWebSearch
UIKeyboardTypeWebSearch
  • UIKeyboardTypeASCIICapableNumberPad(iOS 10.0开始引入)
UIKeyboardTypeASCIICapableNumberPad(iOS 10.0开始引入)

收起键盘

收起键盘的两种方法:

  • 使用endEditing:方法;
  • 注销第一响应者resignFirstResponder

1. endEditing:
在触摸开始方法中,或者添加手势的响应方法中,添加endEditing:

// 触摸开始响应方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    [self.view endEditing:YES];     // 结束视图(或子视图)内所有编辑,即收起键盘
}

2. resignFirstResponder
在按下键盘返回键的代理方法中(这样可以获取相应TextField对象),注销TextField对象第一响应者,将会收起键盘。

/**
 按下键盘返回键时
 应用举例:调用resignFirstResponder方法收回键盘

 @param textField UITextField对象
 @return 我发现返回YES或NO,效果都一样...
 */
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    
    [textField resignFirstResponder];      // 注销第一响应者,收起键盘
    
    return YES;
}

UITextFieldDelegate

设置TextField的代理后,我们可以跟踪TextField的一些编辑状态,进而处理一些事情。
第一步:遵循代理协议

<UITextFieldDelegate>

第二步:设置代理

textField.delegate = self;

第三步:实现代理方法

#pragma mark - UITextField代理方法

/**
 将要开始编辑

 @param textField UITextField对象
 @return YES:允许编辑; NO:禁止编辑
 */
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    
    return YES;
}


/**
 开始编辑,即成为第一响应者,此时光标出现

 @param textField UITextField对象
 */
- (void)textFieldDidBeginEditing:(UITextField *)textField {
    
    NSLog(@"开始编辑");
}



/**
 将要结束编辑
 应用场景:如果当前TextField有内容,则返回YES,允许收键盘或更换TextField;
         当前TextField没有输入内容,返回NO,此时不能收起键盘或者更换TextField
 
 @param textField UITextField对象
 @return YES:允许释放键盘(注销第一响应者); NO:不允许释放键盘(始终是第一响应者)
 */
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    
    // 过滤空格
    NSString *strWithoutSpace = [textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    if (strWithoutSpace.length == 0) {
        return NO;
    }
    return YES;
}


/**
 已经结束编辑
 (即使shouldEndEditing方法返回NO或者调用了endEditing:YES,该方法仍可能调用)
 官方注释:may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
 
 @param textField UITextField对象
 */
- (void)textFieldDidEndEditing:(UITextField *)textField {
    
    NSLog(@"已经结束编辑");
}


/**
 已经结束编辑(iOS 10.0开始引入)
 如果实现,将取代textFieldDidEndEditing:方法

 @param textField UITextField对象
 @param reason 结束原因(正常代理结束或者被迫取消)
 */
- (void)textFieldDidEndEditing:(UITextField *)textField reason:(UITextFieldDidEndEditingReason)reason NS_AVAILABLE_IOS(10_0) {
    
    NSLog(@"已经结束编辑(iOS 10.0开始引入)");
}


/**
 将要改变文字内容时
 应用场景:1.撤销上一次输入
         2.跟踪本TextField所做的最后一次修改
         3.防止文字被改变
         4.限制输入字符类型

 @param textField UITextField对象
 @param range 被修改内容的范围
 @param string 修改内容取代者
 @return YES:允许修改; NO:不允许修改
 */
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    
    return YES;
}


/**
 当按下清除按钮时

 @param textField UITextField对象
 @return YES:允许清除; NO:不许清除
 */
- (BOOL)textFieldShouldClear:(UITextField *)textField {
    
    return YES;
}


/**
 按下键盘返回键时
 应用举例:调用resignFirstResponder方法收回键盘

 @param textField UITextField对象
 @return 我发现返回YES或NO,效果都一样...
 */
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    
    [textField resignFirstResponder];
    
    return YES;
}

限制UITextField输入字符类型及字符个数

1. 限制输入字符类型

在代理方法中作判断,符合返回YES,不符合返回NO。
例如匹配输入为纯数字:

/**
 将要改变文字内容时
 应用场景:1.撤销上一次输入
         2.跟踪本TextField所做的最后一次修改
         3.防止文字被改变
         4.限制输入字符类型

 @param textField UITextField对象
 @param range 被修改内容的范围
 @param string 修改内容取代者
 @return YES:允许修改; NO:不允许修改
 */
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    
    // 匹配纯数字
    NSString *regex = @"[0-9]";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [pred evaluateWithObject:string];    // 匹配返回YES,否则返回NO
}

2. 限制输入字符个数

字符个数决定了字符串的长度。
在代理方法中很难实时地获得字符串长度,因此不好在代理方法里判断。好在苹果提供了监听UITextField的编辑发生改变的事件,可在该事件中作判断。
首先要添加事件:

[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

然后实现事件响应方法:

// 当编辑发生改变
- (void)textFieldDidChange:(UITextField *)textField {
    
    // 获取字符串长度
    NSUInteger strLength = 0;
    for (NSUInteger i=0; i<textField.text.length; i++) {
        unichar uc = [textField.text characterAtIndex: I];
        strLength += isascii(uc) ? 1:2;     // 汉字两个字节
    }
    
    // 如果字符串大于5,裁掉后尾
    if (strLength > 5) {
        textField.text = [textField.text substringToIndex:5];
    }
}

解决键盘遮挡UITextField问题

首先监听键盘显示/收回的系统通知

    /* ----- 解决键盘遮挡问题 ----- */
    // 监听系统要弹出键盘时,发出该通知
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    
    // 监听系统要回收键盘时,发出该通知
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];

实现通知响应方法

#pragma mark - 系统通知调用方法

// 当键盘将要显示时
- (void)keyboardWillShow:(NSNotification *)notification {
    
    // 获取键盘的frame
    CGRect keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    
    // 判断输入框是否被遮挡
    NSInteger distance = textField.frame.origin.y + textField.frame.size.height - keyboardRect.origin.y;
    if(distance>0) {
        // 把界面上移,动画时间0.25s,与键盘同步
        [UIView animateWithDuration:0.25 animations:^{
            self.view.frame = CGRectMake(0, -distance, self.view.frame.size.width, self.view.frame.size.height);
        }];
    }
}


// 当键盘将要回收时
- (void)keyboardWillHide:(NSNotification *)notification {
    
    // 背景view恢复原位
    self.view.frame = self.view.bounds;
}

对了,既然添加了通知,不要忘了在适当的时候移除哟~

- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];     // 移除通知
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容