UITextField一籮筐——輸入長(zhǎng)度限制、自定義placeholder逗物、鍵盤遮擋問題


1.輸入長(zhǎng)度限制:

錯(cuò)誤示范:

textfield輸入限制長(zhǎng)度的需求很普遍搬卒,你看到這個(gè)需求時(shí)也許覺得這個(gè)太簡(jiǎn)單了,只需要像下面這樣寫就可以了翎卓。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSLog(@"-----%@",toBeString);
    if(toBeString.length>5){
        _textfield.text = [toBeString substringToIndex:5];
        return NO;
    }
    return YES;
}

上面的寫法對(duì)純字符(英文和數(shù)字等)有效契邀,但對(duì)中文無效。
這個(gè)代理方法觸發(fā)的時(shí)機(jī)是每當(dāng)在鍵盤上敲擊了一個(gè)字符失暴,導(dǎo)致了輸入框中的藍(lán)色高亮文本發(fā)生改變坯门。string參數(shù)即為敲擊的字符,也即為對(duì)高亮文本來說所發(fā)生的變化逗扒。乍看好像沒什么問題:當(dāng)輸入的字符長(zhǎng)度超過最大限制長(zhǎng)度時(shí)古戴,就從toBeString截取最大限制長(zhǎng)度的子串。
但對(duì)于中文輸入來說是存在問題的:輸入框中高亮的文本并非最終顯示在輸入框的漢字矩肩,通過統(tǒng)計(jì)高亮文本的長(zhǎng)度來限制輸入漢字長(zhǎng)度這明顯是有問題的现恼。這造成的結(jié)果是:當(dāng)我想輸入“喜劇之王”時(shí),便最多只能輸入"xijuz"黍檩,因?yàn)檫@個(gè)長(zhǎng)度統(tǒng)計(jì)的是高亮文本的長(zhǎng)度叉袍,它此時(shí)已達(dá)到最大長(zhǎng)度限制了,但實(shí)際上漢字還未超過最大限制長(zhǎng)度刽酱,導(dǎo)致無法繼續(xù)輸入漢字喳逛,甚至一個(gè)漢字也輸入不了。

怎么改善肛跌?

上面的問題在于對(duì)中文輸入長(zhǎng)度的統(tǒng)計(jì)方式不對(duì)艺配,不能以高亮文本長(zhǎng)度統(tǒng)計(jì)察郁,應(yīng)該以確確實(shí)實(shí)已選取,并已然顯示在輸入框的漢字統(tǒng)計(jì)转唉。限制漢字的選取皮钠,但不限制高亮文本的變化。

但問題是赠法,上面這個(gè)代理方法觸發(fā)時(shí)機(jī)是高亮文本發(fā)生變動(dòng)時(shí)麦轰,而在輸入法選取漢字的動(dòng)作并不會(huì)觸發(fā)其執(zhí)行。如此我們無法得知當(dāng)前輸入框已選的漢字們砖织。

這就需要用到一個(gè)重要的通知了:UITextFieldTextDidChangeNotification,注冊(cè)該通知后不僅高亮文本發(fā)生變動(dòng)時(shí)觸發(fā)款侵,選取漢字時(shí)也會(huì)觸發(fā)。

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

那我們來梳理一下限制控制的邏輯:

1.當(dāng)輸入純字符時(shí)侧纯,只需比較toBeString的長(zhǎng)度和最大限制長(zhǎng)度新锈,超出就截取toBeString的子串就行;
2.當(dāng)輸入漢字時(shí)眶熬,對(duì)高亮文本不做限制妹笆;對(duì)已然顯示在輸入框的漢字進(jìn)行字?jǐn)?shù)統(tǒng)計(jì)和限制,若超出最大限制長(zhǎng)度就截取子串娜氏。

以上用代碼實(shí)現(xiàn)就是:


- (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];
        // 沒有高亮選擇的字拳缠,則對(duì)已輸入的漢字進(jìn)行字?jǐn)?shù)統(tǒng)計(jì)和限制
        if (!position)
        {
            if (toBeString.length > 5) {
                _textfield.text = [toBeString substringToIndex:5];
            }
        }
        // 對(duì)高亮文本不做限制,因?yàn)樗皇亲罱K顯示在輸入框的文本贸弥。
        else
        {   
        }
    }
    // 中文輸入法以外的直接對(duì)其統(tǒng)計(jì)限制即可窟坐,不考慮其他語種情況
    else
    {
        if (toBeString.length > 5) {
            _textfield.text = [toBeString substringToIndex:5];
        }
    }
    
}


2.自定義placeholder:

textfield設(shè)置placeholder只需這樣:_textfield.placeholder = @"請(qǐng)輸入姓名,限制5個(gè)字";
但有時(shí)產(chǎn)品設(shè)計(jì)得需要個(gè)性化一點(diǎn),可能需要對(duì)placeholder的字體绵疲、顏色等進(jìn)行自定制哲鸳。比如:

NSDictionary *attriDict = @{NSFontAttributeName:[UIFont systemFontOfSize:11],
                                NSForegroundColorAttributeName:[UIColor blackColor]};
    _textfield.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"請(qǐng)輸入姓名,限制5個(gè)字"
                                                                       attributes:attriDict];

我看到網(wǎng)上也有人說可以通過KVC給私有屬性賦值的方式修改,但是我試過一次是無效的最岗,也不知為什么帕胆。下來再研究研究。

遇到的問題:
屏幕快照 2016-06-15 22.09.16.png

當(dāng)placeholder字體大小發(fā)生變化后般渡,placeholder的文本可能不再垂直居中顯示了懒豹!

解決方案:

子類化UITextField,重寫placeholderRectForBounds:方法驯用,對(duì)placeholder的偏移量進(jìn)行調(diào)整脸秽。

#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

3.鍵盤遮擋問題:

在有UITextField和UITextView的地方蝴乔,就容易出現(xiàn)鍵盤遮擋問題记餐。這里我要說的解決方案的思路是:通過系統(tǒng)提供的有關(guān)鍵盤的通知UIKeyboardWillShowNotification,UIKeyboardWillHideNotification進(jìn)行全局注冊(cè)觀察。然后需要相應(yīng)的類通過代理方法來處理鍵盤出現(xiàn)和消失時(shí)薇正,界面上輸入框上移和下移的動(dòng)畫片酝。

既然是添加全局的觀察囚衔,則在AppDelegate里注冊(cè)通知:

#import <UIKit/UIKit.h>

typedef enum
{
    KeyBoardWillShow,  // 鍵盤彈出
    KeyBoardWillHide, // 鍵盤退回
}KeyBoardChangeType;


@protocol YWKeyboardDelegate <NSObject>

- (void)ywKeyboardChangeStatus:(KeyBoardChangeType)changeType
                    beginFrame:(CGRect)beginFrame
                      endFrame:(CGRect)endFrame
                      duration:(CGFloat)duration
                keyboardHeight:(CGFloat)kbHeight
                      userInfo:(NSDictionary *)info;

@end






@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@property (nonatomic, weak)id<YWKeyboardDelegate>       ywKeyboardDelegate;  // 代理


@end
#import "AppDelegate.h"
#import "HomeViewController.h"




@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    HomeViewController *homeVC = [[HomeViewController alloc] init];
    UINavigationController *homeNavC = [[UINavigationController alloc] initWithRootViewController:homeVC];
    self.window.rootViewController = homeNavC;
    [self.window makeKeyAndVisible];
    
    [self registerKeyboardNotification]; // 注冊(cè)鍵盤彈出和退回的通知
    
    return YES;
}

- (void)registerKeyboardNotification
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}


- (void)keyboardWillShow:(NSNotification *)notification
{
    [self ywKeyboardChangeStatus:KeyBoardWillShow userInfo:notification.userInfo];
}


- (void)keyboardWillHide:(NSNotification *)notification
{
    [self ywKeyboardChangeStatus:KeyBoardWillHide userInfo:notification.userInfo];
}


// 得到動(dòng)畫時(shí)間、鍵盤高度等信息雕沿。并調(diào)用代理方法练湿,在相應(yīng)類里的代理方法里實(shí)現(xiàn)輸入框上移下移動(dòng)畫等。
- (void)ywKeyboardChangeStatus:(KeyBoardChangeType)changeType userInfo:(NSDictionary *)info
{
    CGFloat durationTime = [info[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    CGFloat keyboardHeight = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
    CGRect beginFrame = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect endFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    
    if([self.ywKeyboardDelegate respondsToSelector:@selector(ywKeyboardChangeStatus:beginFrame:endFrame:duration:keyboardHeight:userInfo:)])
    {
        [self.ywKeyboardDelegate ywKeyboardChangeStatus:changeType beginFrame:beginFrame endFrame:endFrame duration:durationTime keyboardHeight:keyboardHeight userInfo:info];
    }
}



// 一定要記得移除通知
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

比如在登錄界面需要處理鍵盤遮擋問題审轮,出現(xiàn)鍵盤時(shí)賬號(hào)和密碼輸入框會(huì)上移肥哎,避免被鍵盤遮擋;當(dāng)鍵盤消失時(shí)疾渣,輸入框移回原位篡诽。

#import "HomeViewController.h"
#import "AppDelegate.h"

@interface HomeViewController ()<YWKeyboardDelegate>

@end

@implementation HomeViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"登錄";
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    appDelegate.ywKeyboardDelegate = self; // 記得實(shí)現(xiàn)YWKeyboardDelegate協(xié)議
}



#pragma mark ---- ywkeyboardDelegate

- (void)ywKeyboardChangeStatus:(KeyBoardChangeType)changeType beginFrame:(CGRect)beginFrame endFrame:(CGRect)endFrame duration:(CGFloat)duration keyboardHeight:(CGFloat)kbHeight userInfo:(NSDictionary *)info
{
    if(changeType == KeyBoardWillShow){
        [UIView animateWithDuration:duration animations:^{
            self.view.transform = CGAffineTransformMakeTranslation(0, -kbHeight);
        }];
    }
    else if(changeType == KeyBoardWillHide){
        [UIView animateWithDuration:duration animations:^{
            self.view.transform = CGAffineTransformIdentity;
        }];
    }
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市榴捡,隨后出現(xiàn)的幾起案子杈女,更是在濱河造成了極大的恐慌,老刑警劉巖薄疚,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碧信,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡街夭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門躏筏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來板丽,“玉大人,你說我怎么就攤上這事趁尼“<睿” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵酥泞,是天一觀的道長(zhǎng)砚殿。 經(jīng)常有香客問我,道長(zhǎng)芝囤,這世上最難降的妖魔是什么似炎? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮悯姊,結(jié)果婚禮上羡藐,老公的妹妹穿的比我還像新娘。我一直安慰自己悯许,他們只是感情好仆嗦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著先壕,像睡著了一般瘩扼。 火紅的嫁衣襯著肌膚如雪谆甜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天集绰,我揣著相機(jī)與錄音店印,去河邊找鬼。 笑死倒慧,一個(gè)胖子當(dāng)著我的面吹牛按摘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纫谅,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炫贤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了付秕?” 一聲冷哼從身側(cè)響起兰珍,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎询吴,沒想到半個(gè)月后掠河,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猛计,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年唠摹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奉瘤。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勾拉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盗温,到底是詐尸還是另有隱情藕赞,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布卖局,位于F島的核電站斧蜕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏砚偶。R本人自食惡果不足惜孕索,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一飘千、第九天 我趴在偏房一處隱蔽的房頂上張望申鱼。 院中可真熱鬧英妓,春花似錦、人聲如沸酒请。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至布朦,卻和暖如春囤萤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背是趴。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工涛舍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唆途。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓富雅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親肛搬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子没佑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容