美文网首页iOS常用
iOS开发之UI篇(8)—— UITextField

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

作者: 看影成痴 | 来源:发表于2017-11-24 20:39 被阅读67次

    版本
    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];     // 移除通知
    }
    

    相关文章

      网友评论

        本文标题:iOS开发之UI篇(8)—— UITextField

        本文链接:https://www.haomeiwen.com/subject/oeaxbxtx.html