UITextField的一些常用代理方法

1、UITextField 限制输入小数,只能输入小数点后面有两位的代理方法:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{

    NSMutableString * futureString = [NSMutableString stringWithString:textField.text];
    [futureString  insertString:string atIndex:range.location];
    NSInteger flag=0;
    const NSInteger limited = 2;
    int dian = 0;
    for (int i = futureString.length-1; i>=0; i--) {
        
        if ([futureString characterAtIndex:i] == '.') {
            dian++;
            if (dian > 1) {
                return NO;
            }else{
                
                if (flag > limited) {
                    return NO;
                }
                
                //                break;
            }
        }
        flag++;
    }
    return YES;

}
2、限制输入字符长度的方法

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (string.length == 0) {
        if (textField.text.length == 1) {// 删掉了最后一位
            
            return YES;
        }else{//删掉了其中一位
            
            return YES;
        }
    }else{
        NSMutableString * futureString = [NSMutableString stringWithString:textField.text];
        [futureString  insertString:string atIndex:range.location];
        if (futureString.length > 11) {
            return NO;
        }else{
            return YES;
            
        }
    }
}

上面的写法对纯字符(英文和数字等)有效,但对中文无效。
这个代理方法触发的时机是每当在键盘上敲击了一个字符,导致了输入框中的蓝色高亮文本发生改变。string参数即为敲击的字符,也即为对高亮文本来说所发生的变化。乍看好像没什么问题:当输入的字符长度超过最大限制长度时,就从toBeString截取最大限制长度的子串。
但对于中文输入来说是存在问题的:输入框中高亮的文本并非最终显示在输入框的汉字,通过统计高亮文本的长度来限制输入汉字长度这明显是有问题的。这造成的结果是:当我想输入“喜剧之王”时,便最多只能输入"xijuz",因为这个长度统计的是高亮文本的长度,它此时已达到最大长度限制了,但实际上汉字还未超过最大限制长度,导致无法继续输入汉字,甚至一个汉字也输入不了。

怎么改善?

上面的问题在于对中文输入长度的统计方式不对,不能以高亮文本长度统计,应该以确确实实已选取,并已然显示在输入框的汉字统计。限制汉字的选取,但不限制高亮文本的变化。

但问题是,上面这个代理方法触发时机是高亮文本发生变动时,而在输入法选取汉字的动作并不会触发其执行。如此我们无法得知当前输入框已选的汉字们。

这就需要用到一个重要的通知了:UITextFieldTextDidChangeNotification,注册该通知后不仅高亮文本发生变动时触发,选取汉字时也会触发。

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textFeildEditChanged:) name:@"UITextFieldTextDidChangeNotification"
                                               object:_textfield];

那我们来梳理一下限制控制的逻辑:

1.当输入纯字符时,只需比较toBeString的长度和最大限制长度,超出就截取toBeString的子串就行;
2.当输入汉字时,对高亮文本不做限制;对已然显示在输入框的汉字进行字数统计和限制,若超出最大限制长度就截取子串。

以上用代码实现就是:

- (void)textFeildEditChanged:(NSNotification *)notifition
{
    //    UITextField *tf = (UITextField *)notifition.object;

    NSString *toBeString = _textfield.text;
    NSString *lang = _textfield.textInputMode.primaryLanguage; // 键盘输入模式
    if ([lang isEqualToString:@"zh-Hans"]) // 如果输入中文
    {
        UITextRange *selectedRange = [_textfield markedTextRange];
        //获取高亮部分
        UITextPosition *position = [_textfield positionFromPosition:selectedRange.start offset:0];
        // 没有高亮选择的字,则对已输入的汉字进行字数统计和限制
        if (!position)
        {
            if (toBeString.length > 5) {
                _textfield.text = [toBeString substringToIndex:5];
            }
        }
        // 对高亮文本不做限制,因为它不是最终显示在输入框的文本。
        else
        {   
        }
    }
    // 中文输入法以外的直接对其统计限制即可,不考虑其他语种情况
    else
    {
        if (toBeString.length > 5) {
            _textfield.text = [toBeString substringToIndex:5];
        }
    }

}


3、上面方法,如果是计算字节长度,把length方法改为一下在NSString中扩展的方法:

/**
 * 计算字节数
 */
- (int)getByteCount//判断中英混合的的字符串长度
{
    int strlength = 0;
    char* p = (char*)[self cStringUsingEncoding:NSUnicodeStringEncoding];
    for (int i=0 ; i<[self lengthOfBytesUsingEncoding:NSUnicodeStringEncoding] ;i++) {
        if (*p) {
            p++;
            strlength++;
        }
        else {
            p++;
        }
        
    }
    return strlength;
}

4、自定义placeholder:

textfield设置placeholder只需这样:_textfield.placeholder = @"请输入姓名,限制5个字";
但有时产品设计得需要个性化一点,可能需要对placeholder的字体、颜色等进行自定制。比如:

NSDictionary *attriDict = @{NSFontAttributeName:[UIFont systemFontOfSize:11],
                                NSForegroundColorAttributeName:[UIColor blackColor]};
    _textfield.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"请输入姓名,限制5个字"
                                                                       attributes:attriDict];

我看到网上也有人说可以通过KVC给私有属性赋值的方式修改,但是我试过一次是无效的,也不知为什么。下来再研究研究。

遇到的问题:

屏幕快照 2016-06-15 22.09.16.png


当placeholder字体大小发生变化后,placeholder的文本可能不再垂直居中显示了!

解决方案:

子类化UITextField,重写placeholderRectForBounds:方法,对placeholder的偏移量进行调整。

#import "YWTextField.h"

@implementation YWTextField


//控制placeHolder的位置,左右缩20
-(CGRect)placeholderRectForBounds:(CGRect)bounds
{

    CGRect inset = CGRectMake(2, 6, bounds.size.width -10, bounds.size.height);
    return inset;
}


@end

部分摘抄至文章:http://www.jianshu.com/p/d127225aece9#

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值