0

There seems to be lots on this subject. But I couldn't get any of the solutions to work.

My code creates a tableView full of cells with varying contents (based on a JSON), the user should enter the info in each cell. The problem I am having is, when the user taps somewhere outside the cell (i.e. on the tableView background) I want the keyboard to dismiss.

didSelectRowAtIndexPath: method is not good.

touchesBegan: does not fire at all (tableView has user interaction enabled, but I assume there is some other reason).

I have added a gesture to the tableView, but then I cannot start editing.

I know the resignFirstResponder. But I don't know which field is being edited. so I think, I need to go with the endEditing: method. But I just couldn't get it called, when user touches outside of a cell.

Any help would appreciated.

Marco
  • 6,692
  • 2
  • 27
  • 38
Recycled Steel
  • 2,272
  • 3
  • 30
  • 35
  • `resignFirstResponder` is independend from a specific TextFields.You need to write code in UITextViewDelegate and assign it to your class. See this very good answer [here](http://stackoverflow.com/questions/6190276/how-to-make-return-key-on-iphone-make-keyboard-disappear) – JFS Jun 28 '13 at 10:50
  • @JFS Thanks. Okay was really close to that but where would you assign the Deleate to a TextField and TextView in a Custom Cell in a table? Would I do it in the Custom Cell .h or in the cellForRow, this part I can't figure out. – Recycled Steel Jun 28 '13 at 11:20
  • You would do that in the .m file of the tableViewController. Try to put the `(BOOL)textFieldShouldReturn...` method in the controller .m file. – JFS Jun 28 '13 at 11:56
  • Just to make sure leave the `- (BOOL)textFieldShouldReturn:(UITextField *)textField` as it is. Don't replace the `textField` portion with `yourTextField`. – JFS Jun 28 '13 at 12:22
  • In order to make the code working for touching outside the TextField you might need to implement a touch recongizer as well. [Like this](http://stackoverflow.com/questions/5306240/iphone-dismiss-keyboard-when-touching-outside-of-textfield). But I never checked that out myself. Good luck! – JFS Jun 28 '13 at 12:29
  • 1
    @JFS That's not a touch recognizer. That is tap Gesture. If the user didn't tap the screen exactly, then it won't work. I think your delegate is good anyway. It will surely work if he sets the `delegate` for the `textField` while creating it. – Dinesh Raja Jun 28 '13 at 12:55
  • I agree! I'm sure he is going to get that working. – JFS Jun 28 '13 at 13:08
  • @JFS The TextField is now working with the Return button, the TextView does not (which is expected). But I still can not figure out how to tap outside a cell and dismiss. Maybe I just put a "Done" button at the top. Can I not detect a tap on the whole table (excluding Cells)? – Recycled Steel Jun 28 '13 at 13:33
  • @DineshRaja I have set the Delegate for both the Field and View, I am dong it in the cellForRow which is wrong I am sure but I can not think how to set it outside of building the cell. – Recycled Steel Jun 28 '13 at 13:37

3 Answers3

1

If that is a textField as @JFS said, you can set the delegate and resign it in this below method.

- (BOOL)textFieldShouldReturn:(UITextField *)textField

Else If that is a textView, You can add a toolbar with done button as inputAccessoryView to your textView and resign your textView.

I am having two more ideas

Bad Idea:
Try to make an invisible button in the cell background and add an action method to resign it. But this will get confused, when you are using didSelectRowAtIndexPath: method of your UITableView.

Good Idea:(Good one)
UITableView surely will have UIScrollview. So in the scrollViewDidScroll: method, set [self endEditing:YES] will surely work.

Good Idea 2 Create a new View or Button and place it on top of the all views, when a textView is in editing and call the endEditing: method when user touches the view or button.

TO GET A TOUCH DETECTION IN TABLEVIEW:

Some of these Q&A will help you.

https://stackoverflow.com/a/8787019/1083859

Why does my UITableView not respond to touchesBegan?

https://stackoverflow.com/a/8786706/1083859

Community
  • 1
  • 1
Dinesh Raja
  • 8,501
  • 5
  • 42
  • 81
  • Yep the scrollViewDidScroll sounds like a nice option, I will test it and see if it fits the requirements - I will let you know thanks. – Recycled Steel Jul 01 '13 at 10:46
  • @RecycledSteel Sure.. If you find any other way, then don't forget to post it. I am also interested about what you are going to end up with. – Dinesh Raja Jul 01 '13 at 13:00
  • This worked well and looks nice (i.e. it is needed), **- (void)scrollViewDidScroll:(UIScrollView *)scrollView { NSLog(@"Scroll has begun..."); [scrollView endEditing:YES]; }** This still does not get over the problem of just clicking outside a cell and closing the keyboard. Going to try and get a view idea working. – Recycled Steel Jul 01 '13 at 13:36
  • I think you should do `[self.view endEditing:YES];` not `[scrollView endEditing:YES];` and it will only work user scroll the screen. Try that touch detection in tableview idea too.. – Dinesh Raja Jul 01 '13 at 13:52
  • I have found a solution which seems to work well but i could not have done it without your ideas, I have ticked my solution but also upped yours I hope that is okay? – Recycled Steel Jul 01 '13 at 14:18
  • I am glad to know your solution. That's not much important who get the tick or up. It's all about the solution.. Your solution will work good. But I think you still need to consider check the touch detection in tableview why it's not working for you. If you cleared that then you don't need to make a such vague solutions. Because creating a tap gesture for each section is not a good way in my opinion. Whatever try to make it work with a touch detection too. :-) – Dinesh Raja Jul 01 '13 at 14:32
  • I agree and as I said it is not great. I will try the touch in the tableView again but the first time I tried the didSelectRow was not getting called afterwards. It may well be I did something wrong (very possible). – Recycled Steel Jul 01 '13 at 15:55
0

Okay after lots of playing around a managed to figure (something) out, it is not great but works.

Most of the gaps around the table is taken up by section headers (a small amount by the cell walls). To get these areas to call a method I added a gesture to the section header like this;

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
    if (sectionTitle == nil)
    {
        return nil;
    }

    UILabel *label = [[UILabel alloc] init];
    label.frame = CGRectMake(20, 8, 320, 20);
    label.backgroundColor = [UIColor clearColor];
    label.textColor = [UIColor colorWithRed:76/255.0 green:86/255.0 blue:108/255.0 alpha:255/255.0];
    label.shadowColor = [UIColor grayColor];
    label.shadowOffset = CGSizeMake(-0.0, 0.0);
    label.font = [UIFont boldSystemFontOfSize:16];
    label.text = sectionTitle;

    UIView *view = [[UIView alloc] init];
    [view addSubview:label];

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(eventMenuTap)];
    [view addGestureRecognizer:singleTap];

    return view;
}

This also enabled me to customize the label for each section. The net reseult is now I have the keyboard closing when the table is scrolled and if (nearly) anywhere is clicked outside of a cell (i.e. a header) then the eventMenuTap is called.

-(void)eventMenuTap
{
    NSLog(@"Tap has begun...");
    [self.view endEditing:YES];
}

Thanks for all the ideas and help with this.

Recycled Steel
  • 2,272
  • 3
  • 30
  • 35
0

For any passersby, the simplest and most effective solution I have found requires 2 things:

1: Subclass your table view and add the following to its .m:

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // send your own dismiss message; you can use self.delegate to refer to TV's TVC...
    [((SearchVC *)((UITableViewController *)self.delegate).parentViewController).searchBar resignFirstResponder]; 

    // crucial!
    [super touchesBegan:touches withEvent:event];
}

2: Add the following to your TVC:

- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    // send your own dismiss message...
    [((SearchVC *)self.parentViewController).searchBar resignFirstResponder];
}

This works beautifully for me. I initially tried adding touchesBegan to my subclassed cell, but found that was insufficient and, after adding these two things, superfluous.

mkc842
  • 2,361
  • 2
  • 26
  • 38