UITableView
sをセルとして持つUITextField
があります。 UITableView
の背景がタッチされたらキーボードを閉じたいです。 UIButton
のサイズのUITableView
を作成し、UITableView
の後ろに配置することで、これを実行しようとしています。唯一の問題は、タッチがUITableViewにある場合でも、UIButton
がすべてのタッチをキャッチしていることです。何が間違っていますか?
ありがとう!
これは、 ITapGestureRecognizer オブジェクトを作成することで簡単に実行できます(デフォルトでは、これはシングルタップで「ジェスチャー」を検出するので、それ以上のカスタマイズは不要です)。次に、ジェスチャー認識オブジェクトをテーブルビューに添付します。
例えば。おそらくviewDidLoad
メソッドで:
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];
hideKeyboard
メソッドは次のようになります。
- (void) hideKeyboard {
[textField1 resignFirstResponder];
[textField2 resignFirstResponder];
...
...
}
UITextField
オブジェクトの内部に触れた場合、ジェスチャーは発生しません。ただし、UITableView
バックグラウンド、フッタービュー、ヘッダービュー、およびセル内のUILabels
などで発生します。
UITapGestureRecognizerソリューションは、以下を設定した場合、テーブルセルの選択で機能します。
gestureRecognizer.cancelsTouchesInView = NO;
これを行う最善の方法を次に示します。これをやるだけ
[self.view endEditing:YES];
または
[[self.tableView superView] endEditing:YES];
UITableView
はUIScrollView
のサブクラスであるため、以下のデリゲートメソッドを1つ実装すると、非常に簡単で迅速なソリューションが提供されます。ビュー階層がイントロスペクトして現在のレスポンダーを見つけ、レスポンダーのステータスを辞任するように要求するため、resignFirstResponder
を使用する必要はありません。
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.view endEditing:YES];
}
また、UIScrollViewDelegate
をヘッダーファイルに追加することを忘れないでください。
まず、scrollViewWillBeginDragging
を追加して、UIViewController
でUIScrollViewDelegate
をリッスンします。
.hファイル内:
@interface MyViewController : UIViewController <UIScrollViewDelegate>
.mファイル内:
- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {
[self dismissKeyboard];
}
次に、他のインタラクションを聞きます:
- (void)setupKeyboardDismissTaps {
UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
swipeUpGestureRecognizer.cancelsTouchesInView = NO;
swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
[self.tableView addGestureRecognizer:swipeUpGestureRecognizer];
UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
swipeDownGestureRecognizer.cancelsTouchesInView = NO;
swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
[self.tableView addGestureRecognizer:swipeDownGestureRecognizer];
UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];
UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
swipeRightGestureRecognizer.cancelsTouchesInView = NO;
swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.tableView addGestureRecognizer:swipeRightGestureRecognizer];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapGestureRecognizer];
}
次に、dismissKeyboard
を実装します。
- (void)dismissKeyboard {
NSLog(@"dismissKeyboard");
[yourTextFieldPointer resignFirstResponder];
}
そして、私のように、カスタムテーブルセル内のUITextFieldのキーボードを閉じたい場合:
- (void)dismissKeyboard {
NSLog(@"dismissKeyboard");
CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
[customCell.textFieldInCell resignFirstResponder];
}
誰もが検索に役立つことを願っています!!
tableView.keyboardDismissMode = .onDrag
コーディングの楽しみのためのSwiftバージョン:
タップジェスチャレコグナイザーを追加し、キーボードを閉じます。 TextFieldのアウトレットは必要ありません!
override func viewDidLoad() {
super.viewDidLoad()
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}
func handleTap(sender: UITapGestureRecognizer) {
if sender.state == .Ended {
view.endEditing(true)
}
sender.cancelsTouchesInView = false
}
私はこのようにしました:
TableViewControllerでメソッドを作成して、最初のレスポンダーを無効にします(その時点でTextBoxになります)
- (BOOL)findAndResignFirstResonder:(UIView *)stView {
if (stView.isFirstResponder) {
[stView resignFirstResponder];
return YES;
}
for (UIView *subView in stView.subviews) {
if ([self findAndResignFirstResonder:subView]) {
return YES;
}
}
return NO;
}
tableView:didSelectRowAtIndexPath:
前のメソッドを呼び出します。
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
[self findAndResignFirstResonder: self.view];
...
}
セルのタップをブロックしないSwift 3バージョンがあります。
viewDidLoad()
メソッド内:
let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)
hideKeyboard
は次のようになります。
func hideKeyboard() {
view.endEditing(true)
}
UITableViewController
があり、touchesBegan:withEvent:
を実装してもうまくいきませんでした。
うまくいったのは次のとおりです。
迅速:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
view.endEditing(true)
}
Objective-C:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.view endEditing:YES];
}
IOS7をターゲットにしている場合、次のいずれかを使用できます。
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
前者は、テーブルビューがスクロールされたときにキーボードを画面外でアニメートし、後者は、ストックメッセージアプリのようにキーボードを非表示にします。
これらは、UIScrollView
が継承するUITableView
からのものであることに注意してください。
@interface DismissableUITableView : UITableView {
}
@end
@implementation DismissableUITableView
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.superview endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
@end
次に、Nibファイルで、UITableViewのタイプをDismissableUITableViewに設定していることを確認します。
UITableViewは、UIScrollViewのサブクラスです。
私がやった方法は、ユーザーによるスクロールイベントをリッスンしてから、resignFirstResponderでした。コードに実装するUIScrollViewDelegateメソッドを次に示します。
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
この種の問題に取り組むとき、各オブジェクトと親クラスのデリゲートプロトコル(この場合はUITableViewDelegate、UIScrollViewDelegate。イベントの数NSオブジェクトの起動は非常に大きく包括的なものであり、プロトコルを実装してからサブクラス化する方が簡単です。
私は同じ問題を抱えていましたが、ここに私の解決策があります、それは私にとって完璧に機能します:
_<UITextFieldDelegate>
_を実装したビューまたはビューコントローラー
(私の場合、TextFieldCellというカスタムUITableViewCell
があります)、
UITapGestureRecognizer
をプロパティとして宣言します。
_@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
UITextField *theTextField;
UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer;
_
ビュー/コントローラーで初期化します:
_self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];
_
- (void)textFieldDidBeginEditing:(UITextField *)textField
メソッドで、superView
を使用してtableViewに移動し、addGestureRecognizer
を呼び出します。
_[self.superview.superview addGestureRecognizer:gestureRecognizer];
_
- (void)textFieldDidEndEditing:(UITextField *)textField
で、ジェスチャー認識機能を削除します。
_[self.superview.superview removeGestureRecognizer:gestureRecognizer];
_
それが役に立てば幸い。
セルの任意の部分が選択されたときにセルをキーボードで開き、セル以外の場所をクリックした場合はそれを閉じるようにしました。キーボードを開くには:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if (selected)
{
[self.textField becomeFirstResponder];
}
}
(注:セルをサブクラス化しましたが、tableView:didSelectRowAtIndexPath:
UITableView
のデリゲートメソッド
これを行うと、トップのソリューションでは、セルを2回クリックするとキーボードが揺れ、最初にジェスチャ認識機能がキーボードを閉じようとし、次にセルが再選択されてキーボードを開くようになりました。
解決策は、現在選択されているセル内でクリックが発生したかどうかを確認することです。
- (void)viewDidLoad
{
[super viewDidLoad];
//gesture recognizer to close the keyboard when user taps away
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(dismissKeyboard:)];
tap.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tap];
}
-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
{
[self.view endEditing:YES];
}
}
うまく機能するソリューションを見つけました。
IGestureRecognizerDelegateおよびメソッド– GestureRecognizer:shouldReceiveTouch:を使用するために必要です。
次のように、TableViewにジェスチャレコグナイザーを追加します。
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];
次に、shouldReceiveTouchデリゲートメソッドを実装して、UITableViewCellクラスで実行されるタッチを拒否します。 hideKeyboardメソッドは、タッチがUITableViewCellクラスの外部で実行された場合にのみ呼び出されます。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if([touch.view isKindOfClass:[UITableViewCell class]]) {
return NO;
}
// UITableViewCellContentView => UITableViewCell
if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
// UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
return YES; // handle the touch
}
- (void) hideKeyboard{
[textField resignFirstResponder];
}
UITapGestureRecognizerとcancelsTouchesInView = NO
は、セルをタップするとUITextViewsも非表示をトリガーすることを意味します。複数のUITextViewがあり、次のUITextViewをタップする場合、これは悪いです。キーボードが非表示になり、次のtextViewがfirstResponderになり、キーボードが再び表示されます。これを回避するには、タップ位置を確認し、タップがセル上にない場合にのみキーボードを非表示にします。
// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];
// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
CGPoint point = [tap locationInView:tap.view];
[self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}
scrollViewWillBeginDragging:
トリガーするには、tableViewのscrollEnabled
プロパティはYES
でなければなりません
// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.view endEditing:YES];
}
私は解決策を探していましたが、私のコードに合うものを見つけられなかったので、次のようにしました:
http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap
基本的には前述のアプローチの組み合わせですが、サブクラス化や背景ボタンの作成は必要ありません。
これを試して:
viewDidLoad(){
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
tableView.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
UITableView
には便利なbackgroundView
プロパティがあり、以下のSwiftに示すように、セルの選択を台無しにすることなくこの動作を実現しています。
let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)
多くの興味深い答え。 UITableViewシナリオに最適だと思ったソリューションにさまざまなアプローチをコンパイルしたいと思います(私が通常使用するものです):通常、私たちが望むのは、2つのシナリオでキーボードを非表示にすることです:テキストUI要素の外側をタップすると、または、UITableViewを上下にスクロールします。最初のシナリオはTapGestureRecognizerを使用して簡単に追加でき、2番目のシナリオはUIScrollViewDelegate scrollViewWillBeginDragging:メソッドを使用して簡単に追加できます。ビジネスの最初の順序、キーボードを非表示にする方法:
/**
* Shortcut for resigning all responders and pull-back the keyboard
*/
-(void)hideKeyboard
{
//this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
[self.tableView endEditing:YES];
}
このメソッドは、UITableViewビュー階層内のサブビューのtextField UIをすべて再署名するため、すべての要素を個別に再署名するよりも実用的です。
次に、外部のタップジェスチャを介して、次のように却下します。
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setupKeyboardDismissGestures];
}
- (void)setupKeyboardDismissGestures
{
// Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
// UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
// swipeUpGestureRecognizer.cancelsTouchesInView = NO;
// swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
// [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//this prevents the gestureRecognizer to override other Taps, such as Cell Selection
tapGestureRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapGestureRecognizer];
}
TapGestureRecognizer.cancelsTouchesInViewをNOに設定することは、gestureRecognizerがUITableViewの通常の内部動作をオーバーライドしないようにすることです(たとえば、セルの選択を妨げないようにするため)。
最後に、UITableViewの上下スクロールでキーボードを非表示にするには、UIScrollViewDelegateプロトコルscrollViewWillBeginDragging:メソッドを次のように実装する必要があります。
.hファイル
@interface MyViewController : UIViewController <UIScrollViewDelegate>
.mファイル
#pragma mark - UIScrollViewDelegate
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self hideKeyboard];
}
私はそれが役立つことを願っています! =)
リターンキーが押されているときにキーボードを閉じる場合は、textFieldに次のコードを追加してメソッドを返す必要があります:
- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
[textField resignFirstresponder];
}
一部のテキストフィールドにはピッカービューまたはサブビューとして他のものがあるため、上記のメソッドは機能しないため、UITapGestureRecognizerクラスを使用する必要があります。つまり、viewDidLoadメソッドに次のコードスニペットを追加します。
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
ここで、セレクタメソッドに辞職レスポンダを追加するだけです。
-(void)dismissKeyboard
{
[textField resignFirstResponder];
}
それが役立つことを願って、ありがとう:)
テキストフィールドでいっぱいのテーブルを作成したいのはなぜですか?テキストフィールドを含む行ごとに詳細ビューを使用する必要があります。詳細ビューをプッシュするときは、「[myTextField becomeFirstResponder]」を呼び出して、ユーザーがテーブルリストからワンクリックで編集を開始できるようにしてください。
@mixcaの答えは非常に便利ですが、UITextFieldと異なるものがある場合はどうなりますか?私は再帰関数でメインビューのすべてのサブビューを検索することでそれを処理する最良の方法だと思います、以下の例を確認してください
- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder]) {
return YES;
}
}
return NO;
}
また、このメソッドをユーティリティクラスに追加して、@ mixcaの答えのようなタップジェスチャから使用することもできます。
テーブルビューをサブクラス化する(うん!)場合は、 このようなもの が機能する可能性があります。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
BOOL backgroundTouched = YES;
for (UITouch *touch in touches) {
CGPoint location = [touch locationInView:self];
for (UITableViewCell *cell in self.visibleCells) {
if (CGRectContainsPoint(cell.frame, location)) {
backgroundTouched = NO;
break;
}
}
}
if (backgroundTouched) {
for (UITableViewCell *cell in self.visibleCells) {
// This presumes the first subview is the text field you want to resign.
[[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
}
}
[super touchesBegan:touches withEvent:event];
}
これが最終的に作品を作った方法です。さまざまな回答からの提案とコードを組み合わせました。機能:キーボードの非表示、キーボードのテキストフィールドを編集中に移動し、「次へ」および「完了」のキーボードリターンタイプを設定します。
static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;
@interface ViewController () <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
.....// some other text fields
@property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end
@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(tapScreen:)];// outside textfields
[self.view addGestureRecognizer:tapGesture];
// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];
// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];
// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}
// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
...
if([self.emailTXT isFirstResponder])[self.emailTXT resignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
if(textField.returnKeyType==UIReturnKeyNext) {
// find the text field with next tag
UIView *next = [[textField superview] viewWithTag:textField.tag+1];
[next becomeFirstResponder];
} else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
[textField resignFirstResponder];
}
return YES;
}
// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
CGRect viewFrame = self.view.frame;
CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat textFieldBottomLine = textFieldRect.Origin.y + textFieldRect.size.height + LITTLE_SPACE;//
CGFloat keyboardHeight = keyboardSize.height;
BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
if (isTextFieldHidden) {
animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
viewFrame.Origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
return YES;
}
-(void) restoreViewFrameOrigionYToZero{
CGRect viewFrame = self.view.frame;
if (viewFrame.Origin.y != 0) {
viewFrame.Origin.y = 0;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
}
-(void)keyboardDidShow:(NSNotification*)aNotification{
NSDictionary* info = [aNotification userInfo];
keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
}
-(void)keyboardDidHide:(NSNotification*)aNotification{
[self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its zero Origin
}
@end