iOS 一種帶輸入框的自定義alertView的簡易封裝實(shí)現(xiàn)(新增視圖控制器實(shí)現(xiàn)方式)

前言

相信很多人都會選擇自定義alertView,網(wǎng)上也有太多大神封裝了類似的三方庫笛钝,但用來用去质况,感覺最靠譜的,還是系統(tǒng)的玻靡,這也是之前花功夫針對系統(tǒng)的alert進(jìn)行適配封裝的原因之一(iOS (封裝)一句話調(diào)用系統(tǒng)的alertView和alertController)结榄。
但是系統(tǒng)的效果畢竟是局限的,很多時候囤捻,我們僅僅是需要顯示一個遮罩層的提示語臼朗,又或者是比較麻煩的,需要顯示一個可實(shí)現(xiàn)多種交互的提示窗蝎土,這時视哑,還是得自定義……
下面的封裝思路,相對來說簡單一些誊涯,但肯定不是最好的挡毅,甚至因?yàn)椴坏貌坏脑颍昧藛卫@個東西暴构,如果你有更好的改善方法跪呈,還望多多指教段磨。

代碼詳見GitHub:Demo_JXTAlertView

16.3.8更新Demo,添加了模態(tài)跳轉(zhuǎn)視圖控制器實(shí)現(xiàn)alertView彈出
代碼封裝度不高庆械,只是提供一個簡單的實(shí)現(xiàn)思路薇溃。

下面是演示效果(定義的樣式很簡單菌赖,因?yàn)間if幀數(shù)限制缭乘,動畫效果被削弱了):

1.彈性動畫

iOS的動畫效果是很強(qiáng)悍的,彈窗展示時琉用,需要一個彈性動畫去過渡堕绩,彈性動畫的實(shí)現(xiàn)方式有很多,也比較簡單邑时,但難的是自然平滑的效果奴紧,下面的兩種實(shí)現(xiàn),是參考了網(wǎng)上的例子晶丘,兩種方法大同小異黍氮,代碼還是很好理解的,具體參數(shù)可自行調(diào)整:

  • 1.方式一:
- (void)shakeToShow:(UIView *)aView
{
    CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
  animation.duration = 0.2;
  NSMutableArray * values = [NSMutableArray array];
    [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)]];
    [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)]];
    [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9, 0.9, 1.0)]];
    [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]];
  animation.values = values;

    [aView.layer addAnimation:animation forKey:nil];
}
  • 2.方式二:
- (void)shakeToShow:(UIView *)aView
{
    CAKeyframeAnimation *popAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    popAnimation.duration = 0.35;
    popAnimation.values = @[[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.01f, 0.01f, 1.0f)],
                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1f, 1.1f, 1.0f)],
                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9f, 0.9f, 1.0f)],
                            [NSValue valueWithCATransform3D:CATransform3DIdentity]];
    popAnimation.keyTimes = @[@0.0f, @0.5f, @0.75f, @1.0f];
    popAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [aView.layer addAnimation:popAnimation forKey:nil];
}

我采用了第二種方式浅浮,相對來說沫浆,過渡更為順滑些,如果想要實(shí)現(xiàn)和系統(tǒng)的alert動畫相似的效果滚秩,可以去掉values數(shù)組中的倒數(shù)第二項(xiàng)专执,當(dāng)然keyTimestimingFunctions也要去掉對應(yīng)的項(xiàng)。

2.全屏遮罩

一般這類提示窗是顯示在一個半透明黑的遮罩層上的郁油,遮罩層的實(shí)現(xiàn)也有多種方式本股,我采用的是在keyWindow層上添加一個和屏幕尺寸相當(dāng)?shù)陌胪该骱诘膙iew:

_alertBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight)];
_alertBackgroundView.backgroundColor = UIColorFromHEX(0x000000, 0.7);
[[UIApplication sharedApplication].keyWindow addSubview:_alertBackgroundView];

有些人習(xí)慣設(shè)置view的alpha值,但這樣做桐腌,會導(dǎo)致其子視圖也會半透明化拄显,最簡單的還是設(shè)置背景色的透明度,這里采用的是16進(jìn)制色值案站,系統(tǒng)沒有提供關(guān)于16進(jìn)制色值設(shè)置的方法躬审,大都是自己封裝,封裝方法也大同小異嚼吞,只是完善度的問題盒件,我在Demo中使用的是最簡單的一個沒有任何容錯機(jī)制的宏定義方法:

#define UIColorFromHEX(hexValue, alphaValue) \
    [UIColor colorWithRed:((float)((hexValue & 0xFF0000) >> 16))/255.0 \
                    green:((float)((hexValue & 0x00FF00) >> 8))/255.0 \
                     blue:((float)(hexValue & 0x0000FF))/255.0 \
                    alpha:alphaValue]

這種寫法相信十分直觀了,很多不太了解16進(jìn)制色值的轉(zhuǎn)換機(jī)制的朋友舱禽,也可以從上述代碼直觀的去理解炒刁。

3.鍵盤的彈出

鍵盤的彈出是需要考慮的問題,好的progressHUD指示器誊稚,也會考慮鍵盤的彈出翔始,從而自動移動指示器的位置罗心。系統(tǒng)的alert自然不會例外,當(dāng)有鍵盤彈出時城瞎,系統(tǒng)的alert視圖會自動上移渤闷,防止鍵盤的遮蓋。在這里說句題外話脖镀,就是alert動畫中斷系統(tǒng)的鍵盤收起動畫的問題飒箭,這是尤其要注意避免的,一旦在收鍵盤的同時展示alert蜒灰,收鍵盤的動畫就會被強(qiáng)行中斷弦蹂,當(dāng)alert消失時,鍵盤又會詭異的閃現(xiàn)一下……一種解決辦法是强窖,監(jiān)聽鍵盤的收起動畫凸椿,didhide之后再去展示alert。
這里防止鍵盤遮蓋alert的解決辦法也是監(jiān)聽鍵盤的高度去實(shí)現(xiàn)翅溺。

吐槽一句脑漫,有哪位朋友知道如何在鍵盤視圖層添加view嗎?有時候輸入提示想添加在鍵盤上面咙崎,但是一直沒有成功過优幸,鍵盤視圖是在window上,但是卻總也定位不到……

監(jiān)聽鍵盤彈起就很簡單了:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

只是要注意在合適的時機(jī)移除就好叙凡。
鍵盤的高度在監(jiān)聽到的info字典中劈伴,系統(tǒng)的鍵盤信息是比較完善的,但是三方鍵盤就要差很多握爷,甚至有些三方鍵盤的frame是監(jiān)聽不到的……針對這類鍵盤跛璧,除了平時做到放棄使用,還可以根據(jù)經(jīng)驗(yàn)去估計一個值……至于更好的解決辦法就不知道了新啼,可以查閱一些參考資料追城。

// 鍵盤的frame
CGRect keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = keyboardRect.size.height;

有了鍵盤的高度值,就很好處理了燥撞,只需要動態(tài)的去設(shè)置alertView的frame就好了座柱,為了效果自然,也可以添加動畫物舒。具體代碼實(shí)現(xiàn)參考Demo色洞,效果如上圖。

4.Demo中的封裝方法的使用解釋

Demo中的使用情景是填寫圖片驗(yàn)證碼冠胯,需要動態(tài)設(shè)置中間的驗(yàn)證碼獲取按鈕的圖片火诸,還有動態(tài)獲取輸入框的輸入內(nèi)容,這里用的是block荠察,很方便置蜀。

[[JXTAlertView sharedAlertView] showAlertViewWithConfirmAction:^(NSString *inputText) {
    NSLog(@"輸入內(nèi)容:%@", inputText);
} andReloadAction:^{
    [[JXTAlertView sharedAlertView] refreshVerifyImage:[VerifyNumberView verifyNumberImage]];
}];

方法中的第一個block是點(diǎn)擊確認(rèn)鍵的響應(yīng)奈搜,可以獲取到textField的輸入值,第二個blcok是中間的圖片按鈕的點(diǎn)擊響應(yīng)盯荤,用來設(shè)置按鈕的背景圖馋吗,即從網(wǎng)絡(luò)請求到的驗(yàn)證碼圖片,VerifyNumberView類即相關(guān)方法秋秤,只是為了模擬效果而搞笑的……可以自行忽略宏粤。

前面提到封裝時用到了單例,這是因?yàn)閎lock交互響應(yīng)和設(shè)置圖片時的需要航缀,可能還有更好的方式吧商架,請指教堰怨。

5.用模態(tài)跳轉(zhuǎn)視圖控制器方式實(shí)現(xiàn)(此方式僅支持iOS8及以后版本)

iOS8之后的API中芥玉,系統(tǒng)的alert增加了UIAlertController方法,需要使用模態(tài)方式調(diào)用备图。從這點(diǎn)受啟發(fā)灿巧,在自定義時,也嘗試下模態(tài)跳轉(zhuǎn)視圖控制器的方式揽涮。
先看看初始化方法:

- (instancetype)initWithConfirmAction:(ClickBlock)confirmBlock andCancelAction:(CancelBlock)cancelBlcok
{
    if (self = [super init]) {
        self.confirmBlock = confirmBlock;
        self.cancelBlock = cancelBlcok;
        
        self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        self.modalPresentationStyle = UIModalPresentationOverFullScreen;
    }
    return self;
}

其中self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;是設(shè)置跳轉(zhuǎn)的動畫方式抠藕。選擇比較自然的淡入淡出。
self.modalPresentationStyle = UIModalPresentationOverFullScreen;這一句是核心蒋困,這個樣式可以使得模態(tài)推出的頁面透明化盾似,當(dāng)然還需要在推出的視圖中添加這個這個:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = UIColorFromHEX(0x000000, 0.5);
}

先看一個UIModalPresentationOverFullScreen這個枚舉值在API中的說明:

UIModalPresentationOverFullScreen NS_ENUM_AVAILABLE_IOS(8_0),

可以看到,這個枚舉樣式雪标,實(shí)在iOS8之后才支持的零院,系統(tǒng)的UIAlertController也是iOS8之后才有的,從這一點(diǎn)可以簡單猜測系統(tǒng)的alert的實(shí)現(xiàn)機(jī)制村刨。
其他的自定義的方法和上面的大同小異告抄,只是這里不再使用單例,感覺心安了許多……
還要注意一點(diǎn):

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //必須在這里嵌牺,否則動畫無效
    [self showAlertView];
}

[self showAlertView]是創(chuàng)建alert視圖的方法打洼,這一方法,最好是在viewWillAppear中實(shí)現(xiàn)逆粹,如果直接寫在viewDidLoad募疮,模態(tài)跳轉(zhuǎn)的動畫會將我們在創(chuàng)建alert時實(shí)現(xiàn)的彈窗動畫中斷掉,也就是彈窗沒有動畫效果僻弹,這不是我們想要的阿浓。viewWillAppear的執(zhí)行是相對延后的,實(shí)驗(yàn)發(fā)現(xiàn)沒有影響奢方。
根據(jù)這個思路搔扁,也很容易自定義出自己想要的alertView效果了爸舒。

最后還要提一點(diǎn),就是statusBar的樣式稿蹲,如果是UIStatusBarStyleLightContent扭勉,也就是白色文字,全屏遮罩時的半透明黑背景上的白色文字會顯得很是突兀苛聘,iOS7之后涂炎,系統(tǒng)支持在每個視圖控制器中控制statusBar的樣式(注意navigationBar的影響),這樣设哗,用視圖控制器方式實(shí)現(xiàn)alert的全屏遮罩唱捣,相信可以解決這一問題。

參考文章:
1.視圖彈出后放大又縮小的動畫實(shí)現(xiàn)网梢、類似于alertView效果
2.談?wù)刬OS中粘性動畫以及果凍效果的實(shí)現(xiàn)
3.iOS動畫實(shí)現(xiàn):彈簧效果
4.UITextField 文本字段控件 -- IOS (解決鍵盤遮住View及密文設(shè)定的問題)(實(shí)例)
5.iOS開發(fā)之監(jiān)聽鍵盤高度的變化
6.模態(tài)(modal)畫面的顯示方法

·轉(zhuǎn)載請聲明出處·

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末震缭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子战虏,更是在濱河造成了極大的恐慌拣宰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烦感,死亡現(xiàn)場離奇詭異巡社,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)手趣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門晌该,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绿渣,你說我怎么就攤上這事朝群。” “怎么了怯晕?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵潜圃,是天一觀的道長。 經(jīng)常有香客問我舟茶,道長谭期,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任吧凉,我火速辦了婚禮隧出,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阀捅。我一直安慰自己胀瞪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凄诞,像睡著了一般圆雁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帆谍,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天伪朽,我揣著相機(jī)與錄音,去河邊找鬼汛蝙。 笑死烈涮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窖剑。 我是一名探鬼主播坚洽,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼西土!你這毒婦竟也來了讶舰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤翠储,失蹤者是張志新(化名)和其女友劉穎绘雁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體援所,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年欣除,在試婚紗的時候發(fā)現(xiàn)自己被綠了住拭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡历帚,死狀恐怖滔岳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挽牢,我是刑警寧澤谱煤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站禽拔,受9級特大地震影響刘离,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睹栖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一硫惕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧野来,春花似錦恼除、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽令野。三九已至,卻和暖如春徽级,著一層夾襖步出監(jiān)牢的瞬間彩掐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工灰追, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留堵幽,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓弹澎,卻偏偏與公主長得像朴下,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苦蒿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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