1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UICollectionViewのカスタムセル上にて、キーボードが出てきた時に画面を良い感じにスクロールさせる。(追記あり)

Last updated at Posted at 2019-12-15

今回の目的

ViewControllerのライフサイクルが存在しないUICollectionViewCellにて、
キーボードが現れた時に画面を良い感じにスクロールさせる。

ViewControllerのライフサイクルを活用する場合は下記記事をご参照下さい。
(とても参考になります)
UIScrollVIewの上でも、キーボードが現れたときにいい感じにスクロールする

UICollectionViewCellはUIViewControllerを継承していないので、
UIViewControllerのライフサイクルが利用できないので、
通知の登録、解除のタイミングがありません。

実装の方針

UITextFieldDelegateの下記デリゲートメソッドを利用して、
最新の押下されたTextFieldか判定する。

///テキストフィールドを編集する直前に呼び出される
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    return YES;
}

///テキストフィールドの編集が終了する直後に呼び出される
- (void)textFieldDidEndEditing:(UITextField *)textField reason:(UITextFieldDidEndEditingReason)reason{
    //行いたい処理を記載する
}

ロジック

今回のパターンで想定としない処理パターンが1点あります。
Aテキストフィールドを押下後にキーボードを下げずに、
Bテキストフィールドを押下した場合です。

このような処理をされた場合、内部的にはデリゲートメソッドの呼び出しは
A:編集直前
B:編集直前
A:編集終了直後
 と呼び出されます。

仮に編集直後にスクロールを0,0にして元に戻すとしていたら、
Bが適切なスクロール位置に設定されません。

なので、クラスにインスタンス変数を追加して、
**「現在押下されているTextField」**を保存して参照可能にしたいと思います。

///テキストフィールドの編集が終了する直後に呼び出される
- (void)textFieldDidEndEditing:(UITextField *)textField reason:(UITextFieldDidEndEditingReason)reason{
    //行いたい処理を記載する
   if([textField isEqual self.selectedTextField]){
      [self.scrollView setContentOffset:CGPointMake(0, 0)];
   }
}

解説

A:編集直前
B:編集直前
A:編集終了直後

先ほど説明した手順で問題があるのがA編集終了直後でBを編集中なのに、
スクロールを(0,0)に戻している点です。

なので、終了直後に引数で渡されているTextFieldは編集中のTextFieldか、
インスタンス変数と比較してチェックしています。

コード全文

# import "CustomCollectionViewCell.h"

@interface CustomCollectionViewCell()<UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *topTextFiled;
@property (weak, nonatomic) IBOutlet UITextField *bottomTextField;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

///現在フォーカスされているTextField
@property (nonatomic) UITextField *selectedTextField;
@end
@implementation CustomCollectionViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    self.topTextFiled.delegate = self;
    self.bottomTextField.delegate = self;

}

///テキストフィールドを編集する直前に呼び出される
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    
    self.selectedTextField = textField;
    
    switch (textField.tag) {
        case 0:
            [self.scrollView setContentOffset:CGPointMake(0, 0)];
            break;
        case 1:
            [self.scrollView setContentOffset:CGPointMake(0, textField.frame.origin.y - 50)];

            break;
            
        default:
            break;
    }
    return YES;
}

///テキストフィールドの編集が終了する直後に呼び出される
- (void)textFieldDidEndEditing:(UITextField *)textField reason:(UITextFieldDidEndEditingReason)reason{
    if([textField isEqual:self.selectedTextField]){
        [self.scrollView setContentOffset:CGPointMake(0, 0)];
    }
}




@end

補足

参照記事などではキーボードの高さ分、スクロール位置を調整しておりますが、
本クラス内では通知で受け取れるのですが、
解除するタイミングが無いのでキーボードの取得は難しそうですね。

親CollectionViewで通知解除とかいちいちやれば出来るかもです。
改良したらまた投稿します。

途中で書いた [self.scrollView setContentOffset:CGPointMake(0, textField.frame.origin.y - 50)];ですが、一番上から50pt開ければ入力しやすいだろう、
という事で50に設定しております。

調査を追加し、記事を追加しました。

UICollectionViewCell(カスタムセル)で通知を受け取り、キーボードが出た時に良い感じにスクロールさせて戻る。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?