I'm trying create TableViewCells which mimic buttons. This means that on touch down, there should be a highlight effect and on touch up should trigger the standard selected state. This works as intended, but the problem is that there is a split second delay between touch down and the highlighted state appearing. Why is this? How can I make the highlight appear immediately on touch down without the delay?
Here's the code I'm using on my TableView delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[tableView cellForRowAtIndexPath:indexPath] setSelected:YES animated:NO];
// do something here
[[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:NO];
}
I suppose I don't really understand your question as you've asked it. UITableViewCell already acts "like a button" when pressed in the sense of it highlighting. From the looks of your code, it really does nothing that the tableView doesn't do natively.
Basically, the reason you are seeing a delay is because the cell already highlights on touch, and what you are doing is setting Selected to YES, then NO, but the cell already does this, so it's kind of doing the same thing twice, once on it's own, then once forced — this is the reason for the delay you are seeing.
The only thing that should go in didSelectRowAtIndexPath: is the actions you want to happen when the button is pressed, NOT what you want the cell to do or how it should behave upon being touched. There are other delegate methods that would handle these behaviors.
If you are looking to change the highlight color of the cell, then see my question/answer here.
Update
By default, the UITableView code provided by Apple does not contain the deselect method. So when you select the cell it stays selected. To deselect the cell, add the following method to didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/* The following will deselect the cell on touchUp */
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
}
Related
I'm writing an Objective-C app for iOS 8. I was wondering if anyone knows how to tell if a UITableViewCell in a UITableView is on-screen.
For example, if the y value of the UITableView's contentOffset is 0 (meaning that the UITableView is scrolled to the top) and I programmatically select row 2, I don't want to scroll at all because row 2 is already visible (assuming that the UITableView is large enough to show at least 3 rows). However, if I programmatically select row 10 (which is off screen), I want to programmatically scroll to that row.
This is the code I use to scroll to the selected row:
[self.tableView scrollToRowAtIndexPath:[_tableView indexPathForSelectedRow]
atScrollPosition:UITableViewScrollPositionMiddle
animated:NO];
Now, I just need to nest that code inside an if-statement that checks to see if the cell at the currently-selected row is fully visible on-screen.
Any suggestions?
Since you want the selected row to be visible with the least amount of movement, use the method made just for that:
[self.tableView scrollToNearestSelectedRowAtScrollPosition: UITableViewScrollPositionNone animated:YES];
From the docs for UITableViewScrollPositionNone:
The table view scrolls the row of interest to be fully visible with a minimum of movement. If the row is already fully visible, no scrolling occurs. For example, if the row is above the visible area, the behavior is identical to that specified by UITableViewScrollPositionTop. This is the default.
Try this,
NSIndexPath *path = [tableView indexPathForCell:tableView.visibleCells.firstObject];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionNone animated:YES];
There is no way to ask to the tableview if a view is shown at specific time.
What you can do is to be delegate for this tableview and implement this methods:
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView
didEndDisplayingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
You can implementing this methods track the uitableview showing at that moment.
The Situation
I'd like to be able to get information about the title of a cell within a UITableView when the user swipes the cell (to display the "delete" button).
The Code
When the user swipes a cell in the UITableView, this method is fired:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath*)indexPath
The Problem
I need to be able to get the name of the cell the user "swiped" so that my iOS (Obj-C) app can do various operations, etc.
Everything Else
I know that the indexPath has something, but I can't get an NSString from it (which is what I need).
I was also thinking that a workaround such as using a gesture recognizer instead of the above method might be able to provide me with more information about the cell.
Any ideas as to how I can get the name of the cell when the user "swipes to edit / delete"?
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *text = cell.textLabel.text;
// do something with text
}
Please, how does your table work in the first place - you don't seem to understand the basic principles of it. You back your table up with a data model. YOU provide and construct the cells for each indexPath, so you should know how to access the data in your model using that swiped indexPath, no?
Of course you could also ask the tableView delegate (yourself) for the swiped cell by calling tableView:cellForRowAtIndexPath: and then check the labels on that cell.
Have a look at the implementation of your tabkeView:cellForRowAtIndexPath: method all your info of how to get the data should be there...
All in all it's pretty easy, if you provide some code you sure will get more hints.
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.
When I click a cell it selects, but it stays blue on touch up. I want the blue highlight to leave on touch up (but it's important that it highlights in the first place).
This last answer in this post mentions something about willSelectRowAtIndexPath:, but I can't figure out how to use that to do what I want. Also, I do need didSelectRowAtIndexPath: to still be called, I just want the cell to unhighlight on touch-up.
Use the following where appropriate:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
e.g. in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This will deselect the row at the specified index path.
You could also be interested in clearsSelectionOnViewWillAppear property in UITableViewController. If this property is set to yes then the controller clears the selection when the table appears. In default it set to YES.
Reference.
I have a UITableView and I want to add a disclosure button to a cell but only when the cell is selected.
How can i do it?
Thanks
in tableView:didSelectRowAtIndexPath: save the indexPath to a member variable.
in tableview:cellForRowAtIndexPath: check, if the indexPath is the saved one and set cell.accessoryType
Do it in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//bla bla bla
}
Remember to have a variable to remove the button from the previous selected cell
In the table view cell set the accessoryType or accessoryView property. You will want to do this in the -tableView:didSelectRowAtIndexPath: delegate method.
Doing it in didSelect means that the disclosureButton only appears after the user releases the selected cell. If you want ti to appear when the cell is highlighted, you need to subclass UITableViewCell and override setSelected: or setHighlighted:
However, the whole point of a disclosureButton is that the button can be pressed and does something different then simply selecting the cell. For that there is the disclosure indicator. The whole premise of making either of these show up only when the cell is highlighted/selected doesn't seem to serve any good UI design purpose in my opinion...but maybe for what you want it does make sense.