彈跳式視窗的用法

在 iOS 裡彈跳式視窗主要分為由下方昇起的 UIActionSheet 以及Dialog 類型的 UIAlertView

iOS8起 UIAlertView 已 deprecated, 改統一使用 UIAlertController

用法範例如下

 

Simple alert example:
UIAlertController * alert=   [UIAlertController alertControllerWithTitle:@"Password required" message:@"Please enter password" preferredStyle:UIAlertControllerStyleAlert];
     
[self presentViewController:alert animated:YES completion:nil];
Alert with ok button example
UIAlertController * alert=   [UIAlertController
                                alertControllerWithTitle:@"Name required"
                                message:@"Please input name"
                                preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okAction = [UIAlertAction
                       actionWithTitle:@"OK"
                       style:UIAlertActionStyleDefault
                       handler:^(UIAlertAction * action)
                       {
                           [alert dismissViewControllerAnimated:NO completion:nil];
                           // do something
                       }];
[alert addAction:okAction];

[self presentViewController:alert animated:YES completion:nil];
ActionSheet example
UIAlertController * view=   [UIAlertController
                             alertControllerWithTitle:@"Select Sex"
                             message:@""
                             preferredStyle:UIAlertControllerStyleActionSheet];

UIAlertAction* male = [UIAlertAction
                       actionWithTitle:@"Male"
                       style:UIAlertActionStyleDefault
                       handler:^(UIAlertAction * action)
                       {
                           [view dismissViewControllerAnimated:NO completion:nil];
                           // do something
                       }];
UIAlertAction* female = [UIAlertAction
                         actionWithTitle:@"Roaster"
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             [view dismissViewControllerAnimated:NO completion:nil];
                             // do something
                         }];

UIAlertAction* other = [UIAlertAction
                        actionWithTitle:@"Individual"
                        style:UIAlertActionStyleDefault
                        handler:^(UIAlertAction * action)
                        {
                            [view dismissViewControllerAnimated:NO completion:nil];
                            // do something
                        }];


UIAlertAction* cancel = [UIAlertAction
                         actionWithTitle:@"Cancel"
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             [view dismissViewControllerAnimated:YES completion:nil];
                         }];

[view addAction:male];
[view addAction:female];
[view addAction:other];
[view addAction:cancel];
[self presentViewController:view animated:YES completion:nil];

輕鬆處理最下方 UIButton 被 Keyboard 遮住的問題

按鈕放最下方的設計問題

有時候 App 為了設計上的需求,並不採用官方的右上 Edit/Done 的作法,而是將確定的按鈕放在最下方,我相信大家用 Windows 久了,也習慣看到按鈕在最下方。這個作法乍看下沒什麼問題…

BottomButton

不過在實作上,卻會遇到按鍵昇起之後擋住了按鈕的尷尬情況。 = =”

方法一:使用 UITableViewController 自動處理

如果 UI 是使用 UITableViewController 的話,很幸運的它會自動處理這個問題。這裡有個小技巧,要將 TextView 與 Button 放在同一個 Cell 裡,若放在下一個 Cell 的話還是一樣會被擋住。

降下 keyboard 作法:在 button 的動作裡加上

[self.textView resignFirstResponder];
不適用情形:相對的這個頁面就變成可以捲動了,並不一定會符合設計的需求。

方法二: 使用 UITextField的UITextFieldDelegate Protocol

如果上方的文字輸入區塊只需一行的話,可以使用 UITextField 來處理,而藉由 keyboard 的 textFieldShouldReturn 來處理:

作法如下:
1. 讓 UIViewController 實作 UITextFieldDelegate Protocol

@interface TextFieldViewController ()

2. 將按鍵設為 Done

[self.textField setReturnKeyType:UIReturnKeyDone]; 

3. 將 textfield.delegate 設為自己

self.textField.delegate = self;

4. 實作 textFieldShouldReturn 來降下 keyboard

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}
不適用情形:如果上方的文字輸入區塊是允許換行的,就需使用 UITextView, 而上述的作法就無法進行。

方法三: 使用UITextView與 Auto Layout

其實這裡有個很簡單的作法來處理:在 Keyboard昇起的同時,也將 Button 昇到 keyboard 上方即可。


作法如下:

1. 先設好 AutoLayout constraints
TextView 的離上下左右皆為 20
Button 離左右下方為 30
Button 高度=50

2. 將 Button 離下方的 constraint 拉出來設 IBOutlet

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomHeightConstraint;

3. 在 ViewDidLoad 裡增加 listen keyboard notification

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

4. 在 keyboard 昇起與降下時,改變 constraint 的值,這樣就可以達成目的了

#pragma mark - keyboard handling
- (void)keyboardWillShow:(NSNotification *)notification {
    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];

    CGFloat height = keyboardFrame.size.height;

    self.bottomHeightConstraint.constant = height+20;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    NSDictionary *info = [notification userInfo];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    self.bottomHeightConstraint.constant = 20;
    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}

範例 GitHub : https://github.com/orangedream/TextViewAndKeyboard.git

程式撰寫教學

現在寫程式不若二十年前,線上的資源十分的豐富。

我在開發時也常常借用別人的線上教學與模組來加速開發的速度,在使用之餘除了感謝之外,也常在想說應該貢獻一些給這個社群,特別是華文的資源還是相對來說比較缺少。

現在剛好有這個機會跟空間,就一步一腳印的來建立吧~

-Orange,  Jan 2016