背景
UITextField用的也夠多了,這兩天改一個“修改密碼”的bug,結(jié)果發(fā)現(xiàn)一旦設(shè)置了secureTextEntry之后,會有很多的坑搅幅,
這里簡單總結(jié)下:
第一天更新:
// 說明:以下所有的問題點(diǎn)都是New Password這個UITextField
1. keyboard type會改變
背景:
設(shè)置當(dāng)前New Password的keyboardtype是UIKeyboardTypeASCIICapable,
現(xiàn)象:
設(shè)置textfield為暗文的時候呼胚,正常茄唐;但是設(shè)置為明文的時候,鍵盤會變化蝇更,看如下截圖(注意觀察左下角):
這個原因也沒查清楚沪编,應(yīng)該secureTextEntry切換的時候的bug.
那怎么解決呢?
簡單來說簿寂,既然是明文狀態(tài)下會出錯漾抬,那么就在點(diǎn)擊其他textfield的時候,將該password textfield設(shè)置為暗文即可.
即:可以監(jiān)聽textfield的textfield end edit 狀態(tài)常遂,并檢查不是FirstResponder的時候纳令,設(shè)置secureTextEntry為YES
解決代碼如下:
- (void)textFieldChanged {
if (![self.textField isFirstResponder]) {
self.textField.secureTextEntry = YES;
}
}
2. 光標(biāo)不穩(wěn)定
現(xiàn)象:
當(dāng)secureTextEntry在YES和NO之間切換的時候,理論上光標(biāo)應(yīng)該在最后一個字符后面,但是實際會出現(xiàn)當(dāng)有暗文變?yōu)槊魑牡臅r候平绩,光標(biāo)還停留在原來的位置的情況.如下截圖圈匆,藍(lán)色光標(biāo)和內(nèi)容之間的空格:
那怎么解決呢?
這個的解決方法捏雌,想的比較容易跃赚,讓光標(biāo)重新刷新一下就好.
光標(biāo)什么時候回刷新呢?
當(dāng)輸入的text改變的時候會刷新性湿,于是考慮當(dāng)設(shè)置secureTextEntry后纬傲, 將textfield重新賦值一次,即額外手動觸發(fā)器一次text改變:
解決代碼如下:
- (void)showPasswordAction {
// fix cursor bug: reset text to refresh cursor
NSString *tempStr = self.textField.text;
self.textField.text = nil;
self.textField.text = tempStr;
[self setTextFiledSecureTextEntry:!self.textField.secureTextEntry];
}
3. text內(nèi)容顯示不全
現(xiàn)象:
光標(biāo)移到其他textfield上,然后點(diǎn)擊show的button肤频,這時候就會出現(xiàn)部分字母顯示不全的情況:
可當(dāng)光標(biāo)移到這個textfiled上的時候叹括,就會恢復(fù)正常
那怎么解決呢?
如果要解決的話宵荒,比較簡單的方式就是當(dāng)點(diǎn)擊show (就是這個"眼睛")這個button的時候汁雷,將光標(biāo)移到當(dāng)前textfield上.
解決代碼如下:
- (void)showPasswordAction {
// 這種代碼一定要加注釋,否則后面加入的同學(xué)要瘋掉了...??
if (![self.textField isFirstResponder]) {
[self.textField becomeFirstResponder];
}
}
解決后:
4. 字體問題
現(xiàn)象:
password 和new password 設(shè)置的是相同的字體报咳,但是會出現(xiàn)2者字體不一樣的狀態(tài):
字體不對? 于是打了log看暑刃,發(fā)現(xiàn)本來設(shè)置的是系統(tǒng)字體厢漩,但是當(dāng)光標(biāo)移到password的時候,字體會變成new roman字體.
于是嘗試再切換secureTextEntry的時候稍走,重新再設(shè)置下字體
//setLcFont 這個是我們自己定義的一個方法袁翁,無他爾...
[self.textField setLcFont:[LcFont br17]];
But,
But!!!
Failed!
打了log看柴底,設(shè)置后字體是需要的br17字體婿脸,但是實際顯示的卻是錯誤的字體
后來查了半天,才發(fā)現(xiàn)是一個iOS的bug:
可以參考http://stackoverflow.com/questions/35293379
那怎么解決呢柄驻?
/* fix font bug:
1.font will change when secureTextEntry changed
2.iOS bug:font setting will not take effect until you set the font to nil
first
*/
[self.textField setFont:nil];
[self.textField setLcFont:[LcFont br17]];
因禍得福
當(dāng)這個問題解決的時候狐树,第二個光標(biāo)刷新的問題也順道解決了,
當(dāng)然那個問題本質(zhì)也應(yīng)該是字體問題鸿脓,刷新光標(biāo)的解決方案也只是個trick技巧而已
以上抑钟,是昨天遇到的幾個小問題
總結(jié)下代碼就是:
第二天更新:
5. 密碼不顯示省略號
今天又有新需求:
如下,當(dāng)密碼輸入過多的時候野哭,因為顯示不下在塔,所以會顯示"..."
現(xiàn)在是希望,如果是明文密碼拨黔,則可以顯示"...",但如果是暗文蛔溃,則不顯示"..."
開玩笑,這怎么可能,UITextField不是UILabel贺待,不可以設(shè)置line breaks, UILabel 可以設(shè)置的type如下:
// NSParagraphStyle
typedef NS_ENUM(NSInteger, NSLineBreakMode) {
NSLineBreakByWordWrapping = 0, // Wrap at word boundaries, default
NSLineBreakByCharWrapping, // Wrap at character boundaries
NSLineBreakByClipping, // Simply clip
NSLineBreakByTruncatingHead, // Truncate at head of line: "...wxyz"
NSLineBreakByTruncatingTail, // Truncate at tail of line: "abcd..."
NSLineBreakByTruncatingMiddle // Truncate middle of line: "ab...yz"
} NS_ENUM_AVAILABLE(10_0, 6_0);
但UITexField沒有這個屬性徽曲,查了半天,也是相關(guān)UITexField搞不定的用UITextView麸塞,但那是適用于多行顯示的問題秃臣,與本問題無關(guān).
幾經(jīng)周折("人和人的區(qū)別就在這里...")
終于搞定.
那怎么解決呢?
解決方案:
根據(jù)textfield的text的內(nèi)容動態(tài)調(diào)整期frame哪工,這樣就不會出現(xiàn)"..."了 (出現(xiàn)截斷的本質(zhì)是因為width不夠奥此,那就增加寬度就好)
當(dāng)然修改text的frame,這個方法隱藏的比較深了...
- (CGRect)textRectForBounds:(CGRect)bounds {
// Not show truncation text for secureTextEntry,like ****...
if (self.text.length > 0) {
if (self.secureTextEntry && ![self isFirstResponder]) {
CGRect rect = bounds;
CGSize textSize = [self.text sizeOfFont:self.font andWidth:CGFLOAT_MAX];
rect.size.width = MAX(textSize.width, bounds.size.width);
return rect;
}
}
return [super textRectForBounds:bounds];
}
解釋下:
- (CGRect)textRectForBounds:(CGRect)bounds:
lets you set the rectangle for the text when the text field is not being edited.
- (CGRect)editingRectForBounds:(CGRect)bounds:
lets you set the rectangle for the text when the text field is being edited.
// 重寫繪制行為
# 除了UITextField對象的風(fēng)格選項雁比,
# 你還可以定制化UITextField對象
# 為他添加許多不同的重寫方法得院,來改變文本字段的顯示行為。
# 這些方法都會返回一個CGRect結(jié)構(gòu)
# 制定了文本字段每個部件的邊界范圍章贞。以下方法都可以重寫祥绞。
– textRectForBounds: //重寫來重置文字區(qū)域
– drawTextInRect: //改變繪文字屬性.
//重寫時調(diào)用super可以按默認(rèn)圖形屬性繪制,若自己完全重寫繪制函數(shù),就不用調(diào)用super了.
– placeholderRectForBounds: //重寫來重置占位符區(qū)域
– drawPlaceholderInRect: //重寫改變繪制占位符屬性.
//重寫時調(diào)用super可以按默認(rèn)圖形屬性繪制,若自己完全重寫繪制函數(shù)鸭限,就不用調(diào)用super了.
– borderRectForBounds: //重寫來重置邊緣區(qū)域
– editingRectForBounds: //重寫來重置編輯區(qū)域
– clearButtonRectForBounds: //重寫來重置clearButton位置,改變size可能導(dǎo)致button的圖片失真
– leftViewRectForBounds:
– rightViewRectForBounds:
結(jié)果如下:
參照 http://stackoverflow.com/questions/3287312
第三天更新:
6. placeholder 的字體問題
6.1 背景:
大家不知是否記得我們的第四條字體問題蜕径,為了修改字體,使用了如下方法:
[self.textField setFont:nil];
[self.textField setLcFont:[LcFont br17]];
這個本來安心的交給測試了败京,結(jié)果產(chǎn)生了新的問題:
6.2 現(xiàn)象:
這個方法會改變placeholder的字體:
默認(rèn)情況:
當(dāng)什么都不輸入兜喻,直接點(diǎn)擊眼睛:
(即執(zhí)行如上setLcFont設(shè)置字體的操作之后)
大家可以看到"6-20 characters" 這個字符變小了.
至于為什么會發(fā)生這個,很顯然是個蘋果的bug赡麦,
首先通過先設(shè)置為nil再設(shè)置字體的方式朴皆,本身就很詭異,自然會引發(fā)出新的問題.
目前表現(xiàn)就是placeholder的字體不對了
6.3 那怎么解決呢
那我們就看下怎么修改placeholder的字體泛粹,
6.3.1 attributeString
大概看了下遂铡,常見思路就是,設(shè)置attributestring晶姊,這個看上去可以扒接,但是得把代碼中所有的都這么改,而且attribute本身設(shè)置起來--"又臭又長"们衙,不太實用
所以pass.
6.3.2 placeholderLabel
placeholder 本質(zhì)是個label钾怔,
有個比較常見的設(shè)置placeholder color的方法:
[textfield setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
當(dāng)然這個函數(shù)也直接可以通過xcode進(jìn)行設(shè)置完成.
但這個有人反饋?zhàn)约阂驗檫@個被APPSTORE拒絕過.
所以還是pass
6.3.3 自己來渲染
6.3.3.1 textRectForBounds啟發(fā)
昨天有介紹過textRectForBounds這個方法,那自然對應(yīng)也有placeholder相關(guān)的方法:
/*
Draws the receiver’s placeholder text in the specified rectangle.
You should not call this method directly.
If you want to customize the drawing behavior for the placeholder text,
you can override this method to do your drawing.
By the time this method is called, the current graphics context is already configured with the default environment and text color for drawing.
In your overridden method, you can configure the current context further and then invoke super to do the actual drawing or do the drawing yourself.
If you do render the text yourself, you should not invoke super.
*/
- (void)drawPlaceholderInRect:(CGRect)rect {}
這個如果你完全自己定義placeholder的text蒙挑,那就不需要調(diào)用super方法宗侦,否則建議不然忘記super方法.
6.3.3.2 實現(xiàn)drawPlaceholderInRect
show me the code:
- (void)drawPlaceholderInRect:(CGRect)rect {
//draw place holder.
[[self placeholder] drawInRect:rect withFont:[UIFont systemFontOfSize:17]];
}
okey,這樣一來忆蚀,字體就保證了矾利,但是run起來會發(fā)現(xiàn)懊悯,字體的顏色和位置不對了 ---- 始終處于置頂?shù)母杏X
6.3.3.3 解決對齊問題
顏色的問題好解決,我們先來看看置頂?shù)膯栴}:
-
調(diào)整垂直對齊方式
如下:
self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
發(fā)現(xiàn)無效. 然后依次設(shè)置了如下全部ContentVerticalAlignment對齊方式后梦皮,只有AlignmentBottom會置底炭分,其他都會置頂.
typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) {
UIControlContentVerticalAlignmentCenter = 0,
UIControlContentVerticalAlignmentTop = 1,
UIControlContentVerticalAlignmentBottom = 2,
UIControlContentVerticalAlignmentFill = 3,
};
-
drawInRect
前面的不行,那只能從drawInRect下手了剑肯,這里斷點(diǎn)查了下rect如下:
截圖可以看到y(tǒng) = 0捧毛,所以導(dǎo)致無法居中,猜想super的
drawPlaceholderInRect方法里面應(yīng)該是做了一些對齊的操作让网,那我們也自己來實現(xiàn)一下吧呀忧,這個倒是不難
CGSize size = [self.placeholder sizeOfFont:self.font andWidth:CGFLOAT_MAX];
CGRect placeholderRect =
CGRectMake(rect.origin.x, (rect.size.height - size.height) / 2,
rect.size.width, size.height);
參照http://stackoverflow.com/questions/19093604
-
還差一點(diǎn)
在‘2’的基礎(chǔ)上測試之后,發(fā)現(xiàn)位置是終于居中了溃睹,但是點(diǎn)擊"eye" buton的時候而账,位置還是會稍微的有一點(diǎn)點(diǎn)偏移,查了下代碼因篇,如果rect會有改變泞辐,應(yīng)該是UITextfied在你編輯狀態(tài)和非編輯狀態(tài)的時候,位置會有一定的出入(這個稍微留心點(diǎn)竞滓,都能發(fā)現(xiàn))
所以我們的代碼還需要再做一丁點(diǎn)的改變:
CGRect placeholderRect =
CGRectMake(rect.origin.x, (self.height - size.height) / 2,
rect.size.width, size.height);
再測試一下咐吼,okey.
6.3.3.3 解決顏色問題
這個沒什么方法,扣色調(diào)整下就行商佑,不過整體扣色還是不太準(zhǔn)確锯茄,需要自己再去調(diào)試.
比較常見的顏色是
[UIColor colorWithWhite:0.70 alpha:1]
不過我試下來,感覺還是不對茶没,自己調(diào)整了肌幽,大概顏色是:
[UIColor colorWithHexString:@"CDCDC8"] colorWithAlphaComponent:0.8]
不過這個不是重點(diǎn)了,找自己家里的UI去做就好了...