make custom UIView become first responder in custom UITableViewCell - objective-c

I have three UITableViewCell subclasses. I'm displaying these in a table view in a view controller. I have, in the view controller, returning nil for tableView:willSelectRowAtIndexPath: since I want the UITextFields, in two of my UITableViewCell subclasses, to get focus and become first responder.
For the third UITableViewCell subclass, I have a custom UIView subclass that houses a UIWebView. Currently the div in the html content loaded in the UIWebView is one line tall. I previously made the div height 100% but found that scrolling started to act up. If I tap in the div the keyboard comes up. However, if the user taps any where else within this custom UITableViewCell the UIWebView div is not selected and the keyboard does not come up.
How can I get either my custom UITableViewCell or custom UIView subclass to become the first responder? Or am I going about this the wrong way?

I believe you're going about this the wrong way. Returning nil for tableView:willSelectRowAtIndexPath: won't really help your cause here.
Instead, you have a couple options. First, you could make a UIButton that sits behind your text fields in your table cell which fills the entire view, and then respond to touches on it and tell the text field to become active. Like so:
Wire up the button within your UITableViewCell subclass:
[self.button addTarget:self action:#selector(handleTouch) forControlEvents:UIControlEventTouchUpInside];
Set focus on the text field when touched:
- (void)handleTouch
{
[self.textField becomeFirstResponder];
}
The other option, and the one I like less, is to handle the selection of the cell in the delegate methods and tell the cell's textfield to become active. Like so:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCellSubclass *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell.textField becomeFirstResponder];
}
In which of course you would need to add a textField property to your MyCustomCellSubclass in order to do this.
Hope this helps!

Related

iOS animate partial cells to show full cell

I've got an UITableViewCell with a UITextField in it. When I click the UITextField I want to make sure the entire cell is visible in the tableView. I did this in textfieldDidBeginEditing, like so:
- (void) textFieldDidBeginEditing:(id)textField {
TTTableViewCell *cell = (TTTableViewCell *)[self.tableView cellForRowAtIndexPath:objc_getAssociatedObject(textField, kIndexPathId)];
[self.tableView setContentOffset:CGPointMake(cell.frame.origin.x, cell.frame.origin.y - self.tableView.sectionHeaderHeight) animated:YES];
}
This works perfectly when the user goes down the list. Expect when to user taps a cell which is partial visible on the top it doesn't reveal the entire cell just moves a bit.
Does someone know a solution to this problem?
There are UITableView methods to solve exactly this. You can use scrollToRowAtIndexPath:atScrollPosition:animated: to ask the table view to bring a cell to the top by passing UITableViewScrollPositionTop.
(You might first want to check if it's already visible to ensure it doesn't scroll unnecessarily.)

How do I re-use my custom UITableViewCell in various UITableView?

I have three separate "UIViewControllers" in my app. Each has UITableView attached to it.
First UITableView displays just a single table of rows of data (news items).
Second UITableView displays a search view, which has a few sections where users type in different search criteria.
Third UITableView displays the article details.
In each of the UITableView, there is a button.
First UITableView has "Load more articles" button.
Second UITableView has "Search" button
Third UITableView has "Visit article page" button.
Since all three views are UITables, I created a custom UITableCellView and added to each of the UITableViews. Here's an example of my "ButtonCell" in the 2nd UITableView
ButtonCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ButtonCell"];
NSString *cellText = #"Search";
[[cell buttonLabel] setText:cellText];
return cell;
This works well - exactly how I want it.
Now I added the same "ButtonCell" to the first and third UITableView, but a few strange things happened.
The background color of the ButtonCell is not correct - in the ButtonCell ".xib" file, I set it to a blue-ish color. This works well for the 2nd UITableView, but for others, it's just "white".
The ButtonCell doesn't have "rounded corners" anymore.
Any ideas on how to properly "re-use" my custom button cell in any UITableViews?
It sounds like your second table is grouped, and the other two plain (you get rounded corners with a grouped table view style). Setting the color of custom cells in IB for plain tables doesn't work. You should set the color of your cells in the tableView:willDisplayCell:forRowAtIndexPath: delegate method:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [UIColor colorWithRed:.67 green:.93 blue:1 alpha:1];
}

How to get textFields in custom UITableView

Very beginner obj-c question.
I have plain UITableView with two sections, but I am interested only in first section now. This section have four custom cells (inherited from standard UITableViewCell), and they have a UITextField's as a property.
I need to improve custom Input Accessory View with buttons "Next", "Previous"(for switch between textFields in tableview) and "Done" (dismissimg of keyboard). http://uaimage.com/image/62f08045
In -textFieldShouldReturn i set tags for textFields from 0 to 3. My next plan is to add textFields into NSMutableArray in -viewDidLoad and then just set and resign first responder for the textFields. Approximate code listing for "Next" button:
- (void) inputAccessoryViewDidSelectNext:(FDInputAccessoryView *)view {
for (UITextField *textField in [self textFieldsArray]) {
if ([textField isFirstResponder]) {
[textField resignFirstResponder];
UITextField *field = [[self textFieldsArray] objectAtIndex:textField.tag + 1];
[field becomeFirstResponder];
}
}
}
Questions:
Is this a right way or maybe there is a better approach to solve problem?
Do I need to tag textfields or use indexPath of cells in what they are built in? (or what is the best to track textFields?)
And the main question: what is the syntax to "get" textField from cell?
Sorry for the dumb questions, I am a very beginner.
Thanks,
Alex.
I think you have the right idea, but a few things come to mind:
Just to be safe, don't start with tag number 0. Every view has a tag number defaulted to 0, so you may get something unexpected.
Don't set the text view's tags inside of the textFieldShouldReturn, set the tags in cellForRowAtIndexPath or viewDidLoad, wherever you init the textFields.
Add the textFields to the cell's contentView, not the cell itself.
You don't have to resign first responder from the first text field, you can just becomeFirstResponder on the new one.
Make sure you're handling the last text view edge case: You could loop around to the first text field or simply dismiss the keyboard at the end.
If you want to get the textField in the cell:
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:
[NSIndexPath indexPathForRow:ROW_NUMBER inSection:1]];
UITextField *textField = (UITextField *)[cell.contentView viewWithTag:TEXT_FIELD_TAG];

Preventing blue background on selecting a cell

I want to remove the selection color that appears when I touch a cell in my tableview.
In IB there is a "shows selection" checkbox that does nothing and it seems from what I can gather that it is just a bug in IB.
But then there is the
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
that I can set to each cell.
This also does nothing, so this is where I am stuck, all documentation say that if I set this property it should not appear but it does.
I push another UIViewController on a UINavigationController, and when I go back to the view in question, the blue background on the cell is stuck until I touch another one.
The only thing special is that I instantiate this UITableViewController with the help of storyboard and I use prototype cells. Then I put it inside a UIScrollView to have horizontal paging between multiple UITableViewControllers. There is no way to access the navigation controller when I do this so I pass the UINavigationController along to the UITableView.
Sorry that I can't make the keywords appear as code, it says I should press the tab key then type a $ but that moves my cursor to tags.
You might try to set the selectedBackgroundView of your cell like this :
customCell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
In the delegate method cellForRowAtIndexPath
From code you can use (for example for grey):
cell.selectionStyle = UITableViewCellSelectionStyleGray;
And put this at:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
In your ViewController.
The solution was to set the style on the prototype cell in IB. Many things are wierd about prototype cells.

How to make a custom tableView cell accessory

I have not yet found any really good examples on how to do this. There is an image that I want to use as the accessory button and when I put it in and click on it doesn't work. So it looks correct but doesn't work...
Here is my code:
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
cell.accessoryView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"TableView_Green_Disclosure.png"]];
So how do I get my UIImageView to call accessoryButtonTappedForRowWithIndexPath whenever it is tapped?
A thorough reading of accessoryView and accessoryType would reveal that they are mutually exclusive ways to customize a cell.
Setting the accessoryType will cause the table view delegate method to be called when it is tapped.
Setting the accessoryView will ignore the setting of accessoryType and give you something to display. If you want to receive a callback from the custom view you've put in place, it should be a control that is wired up to do so. (Or any view with a gesture recognizer.)
If you use a button, and set its action to accessoryTapped:, you will receive the button as the "sender" argument. You can walk up the view hierarchy until you find a table view cell, and then ask your table view what the indexPath of that cell is. This will then get you an index into your model objects and you be able to act on it appropriately.
Alternate to the button, you can enable interaction on the UIImageView above, and add a gesture recognizer to it.
To make the button actually do something, you'll need to implement - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath from UITableViewDelegate.
When an accessory button is tapped in a row, this method will be called and you'll have the chance to act appropriately using the passed in index path to determine which row's accessory was tapped.
Check the blog post hdr->cmdline for creating custom accessory view for UITableView.
The author used UIButton objects with images for custom accessory view.
To make use of the accessoryView - you would need to set the cell's accessoryType to UITableViewCellAccessoryNone deposit a UIButton (with associated image) into the cell and then wire it up to receive user touches. You might use something like the code below as the IBAction response to the cell's UIButton being touched:
- (IBAction) accessoryButtonPressed:(id) sender
{
NSUInteger pathInts[] = { 0,0 };
pathInts[1] = self.currentselectedrow; // ivar set when tableview row last selected
NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:pathInts length:2];
[self tableView:mytableview accessoryButtonTappedForRowWithIndexPath:indexPath];
}
The UIButton would be wired to execute this glue code by way of a line inside your tableview's "cellForRowAtIndexPath:" function
[thecell setButtonTarget:self action:#selector(accessoryButtonPressed:)];
One thing I noticed is that the UIButton seems to want a 'swipe right' versus a simple 'tap' touch in order to trigger the event - but it could be my beta iOS that's the problem. Note that I had added a UIButton* object named 'cell_accessoryButton' to the Custom Cell source.
In the cell's source you'd support the 'setButtonTarget' call with code like this:
- (void) setButtonTarget:(MyViewController*)inTarget action:(SEL) inAction
{
[self.cell_accessoryButton addTarget: inTarget
action: (SEL) inAction
forControlEvents: UIControlEventTouchUpInside];
}
It's so much easier to just use the accessoryType reference and let iOS do the heavy lifting - but, if you want a custom graphic, etc - this is another path that works.