I'm trying to change states of the label in my table view cell.
I want to keep a cell selected while I push a different view controller and move back to the view controller with my tableview.
When I select another row I want to remove highlight of previously selected row's lable (deselect the previously selected row) and Highlight the current row's label.
Is - (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated supposed to call - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated with highlighted 'NO' for that Cell ?
Note: I'm not UITableViewController.
Keep cell selected:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selected = YES;
//Other code
}
Ensure that the class cell don't have selected = NONE in interface builder.
Unselect last row:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *currentSelectedIndexPath = [tableView indexPathForSelectedRow];
if (currentSelectedIndexPath)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selected = NO;
}
return indexPath;
}
First, you should set TableviewCell properly [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; in method :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Other then this, you can set custom background of selected cell by
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor colorWithWhite:0.97 alpha:1.0];
bgColorView.layer.masksToBounds = YES;
[cell setSelectedBackgroundView:bgColorView];
For Your highlight selected cell problem, you can use Simple flag like
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *ip= [NSIndexPath indexPathForRow:flagForLastSelectedRow inSection:0];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
flagForLastSelectedRow=indexPath.row;
}
Related
I'm trying to achieve airbnb look for my UITableViewController.
separators are not in the full width of the screen
each cell has a unique size and background color
I've managed to tackle #2 using static table and setting each cell size in IB but have the following problems:
setting a background color in IB didn't take (changed both background color as well as tint)
I wish to "delete" a cell programmatically when it has no content but the only function that returns cell height - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
is generic for all cells and is called prior to populating the cells with data, so at this method I can't decide if the cell should be deleted or not.
I think you should use the delegate method willDisplayCell: forRowAtIndexPath: of the table view. This delegate method is called just before the cell is ready to be displayed on the table view. In this delegate you will have the cell created, if you need some modifications you can do here, which will be reflected just before the cell is displayed.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell setBackgroundColor:[UIColor redColor]];
// and all other cell customizations
}
You could set separatorInset and layoutMargins properties of table view before layout subviews and cell's separatorInset and layoutMargins properties before displaying cell.
For setting custom cell's height you may get needed cell by calling a table view data source method instead of call cellForRowAtIndexPath: method of table view.
Example:
// 1. Make full width separators:
- (void)viewWillLayoutSubviews {
if ([self.tableView respondsToSelector:#selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:#selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
#pragma mark - Table view data source
// 2.Customize cells background color and height
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = [NSString stringWithFormat:#"s%ld-r%ld", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
if (indexPath.row % 2) {
cell.backgroundColor = [UIColor redColor];
cell.contentView.backgroundColor = [UIColor whiteColor];
cell.textLabel.text = cellIdentifier;
} else {
cell.backgroundColor = [UIColor cyanColor];
cell.contentView.backgroundColor = [UIColor whiteColor];//background color of contentView overlaps cell's background color
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; //getting cell at indexPath
if ([self isCellEmpty:cell]) {
return 22;
}
return 44;
}
- (BOOL)isCellEmpty:(UITableViewCell *)cell {
return !cell.textLabel.text.length; //Place your code for checking cell's content
}
I have a question about UITAbleViewCell's.
I have implemented UITableViewDelegate method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
cell.textLabel.textColor = [UIColor redColor];
cell.textLabel.text = #"Title";
}
After I click on desired cell, nothing happens...
Why it doesn't work as I expected? Also, what should I do to make it work?
You have to create some base model for cell states e.g:
#property NSString *modelState = #"red"; // this is fast hint, but it can be a enum with states.
all cell will have one title after tap.
... other controller code...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.restaurantTable dequeueReusableCellWithIdentifier:#"cell_ID"];
// cell customization method
[self customizeCell:cell accordingToStateStr:modelState];
return cell;
}
... other controller code...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
// Set other state for cell
self.modelState = #"red";
[tableView reloadData];
}
- (void)customizeCell:(UITableViewCell*)cell accordingToStateStr:(NSString *)str {
if ([str isEqualToString:#"red"]) {
cell.backgroundColor = [UIColor redColor];
cell.textLabel.textColor = [UIColor redColor];
cell.textLabel.text = #"Title";
} else if(...) {
//Other options..
}
}
[tableView reloadData]; - will trigger once again "cellForRow" method and your table will be redrawn according to new model.
You can use for cell states emuns instead NSString object (this is only scaffold for you).
Try this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// config the selected cell
....
}
You should ask the UITableView for the cell directly rather than ask its delegate (self in your code). Cause its delegate may dequeue or create a fresh cell rather than giving you the cell seleceted.
Issue: I only want to show the selected cells with checkmark. I don't want the grey highlight.
I tried:
cell.selectionStyle = UITableViewCellSelectionStyleNone
but didn't work.
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
ProfileSelection *profile = [self.profileSelections objectAtIndex:indexPath.row];
cell.textLabel.text = [profile profileName];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.profileSelectionsTableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
ProfileSelection *profile = [self.profileSelections objectAtIndex:indexPath.row];
self.mobileProfileId = [profile.profileId stringValue];
[_continueButton setEnabled:YES];
}
How about this:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
The selectionStyle property should be enough to remove the highlight.
If you want to show the checkmark after the used has selected the row, you need to implement the tableView:didSelectRowAtIndexPath: method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView cellForRowAtIndexPath:visibleIndexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
In Swift, the easiest way is to deselect a cell without animation right after it has been selected:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
}
delete your this function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Try to use this your problem will be solved
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone
cell.textLabel.text = #"Checking Table View";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Go to Storyboard. Select your Table View Cell. Set Selection to None. Then add below codes:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
This thread looks a bit old, but I actually came across a decent solution for this recently. In case anyone stumbles across this thread, I figure I might as well post an answer. Especially since I spent hours trying to track this down.
I can't find my original sources anymore, but here's what I found out:
The highlight is made by a background view on the UITableViewCell on the selectedBackgroundView property. If we have a subclass of the table cell, we can detect the transition to the editing state with willTransitionToState: and set the background view to one that is clear/white instead of the blue/gray styles.
Here's what I ended up doing, and it works pretty well.
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
// To remove the blue/gray highlight on the table cell when selected,
// set the selection background to a clear view.
if (state & UITableViewCellStateShowingEditControlMask) {
// If we're moving to an edit state, set the custom background view.
UIView *bgView = [[UIView alloc] init];
[bgView setTintColor:[UIColor whiteColor]];
[bgView setBackgroundColor:[UIColor clearColor]];
[self setSelectedBackgroundView:bgView];
} else {
// Otherwise, just remove it completely.
// The system should handle the rest.
[self setSelectedBackgroundView:nil];
}
}
The plus side to this over the other solutions I've seen is that this one is quite minimal. No need for tracking instance variables or anything else.
I have a tableView, with custom cells.
In each cell i have a UIButton. When i click the button inside the cell i want that cell to highlight, but when i click o the cell i don't want this to happen.
Do you know any way to do this?
thank you
until now i have this code:
- (IBAction)buttonMethod: (id)sender {
UIButton *b = (UIButton *) sender;
UITableViewCell *cell = (UITableViewCell *)[[[sender superview] superview] superview];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[cell setSelected:YES animated:YES];
}
but the cell is highlighted also in -didSelectRow.
- (UITableViewCell *)tableView: (UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSAssert(cell, #"cell -> nil");
NSDictionary *cellData = [_data objectAtIndex:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[cell populateCellWithData:cellData];
return cell;
}
Use this UITableViewDelegate method:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
This way, cells can't be selected when the user taps on them, but you can still select them programatically.
Also using
selectRowAtIndexPath:animated:scrollPosition:
on your UITableView , instead of setSelected:animated: on UITableViewCell might be better. Cells can be reused and the selection will probably disappear when it happens.
You have to add following line in tableView delegate method cellForRowATIndexPath.
cell.selectionStyle =- UITableViewCellSelectionStyleNone;
You have to set cell.selectionStyle = UITableViewCellSelectionStyleNone; in cellForRowAtIndexPath method of tableView.
So you can set this style in - (IBAction)buttonMethod: (id)sender. You can add this line at the end. See below:
- (IBAction)buttonMethod: (id)sender {
UIButton *b = (UIButton *) sender;
UITableViewCell *cell = (UITableViewCell *)[[[sender superview] superview] superview];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[cell setSelected:YES animated:YES];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
Just use UITableViewDelegate like this
-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
but If I were you, I would change the background color of cell in [buttonMethod:] with UITableViewCellSelectionStyleNone
I have a table view
and when I click the cell everything is fine
however, when I remove my fingers from the phone, the cell stays selected
how can I make it become deselected when the user stops touching the given cell and does not touch another cell
Simple :
In this method : didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UIActionSheet *photoPicker ;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
you have to set the style in cellForRowAtIndexPath or change the cell in willSelectRowAtIndexPath and change back in didSelectRowAtIndexPath.
For example
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// ...
cell.selectionStyle = UITableViewCellSelectionStyleBlue; // or an other style
// ...
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// ...
[tableView deselectRowAtIndexPath:indexPath animated:NO];
// ...
}
Put the following in the UITableView delegate.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell setSelected:NO animated:YES];
}
Have you considered to handle the touch events?
For example: Add a UITapGestureRecognizer, detect which cell is being touched by using the -(CGPoint)locationInView:(UIView *)view method. Mark the cell as selected when the touch begins and mark as deselected when the touch ends.
Have you assigned delegate to UITableView?
self.tableView.delegate = self;
That is the reason why you experience this
this does not work - the cell does not show indication of being
selected
In tableView:didSelectRowAtIndexPath:, set the selected property of the cell to NO using the method setSelected:animated:.
E.g.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
[cell setSelected:NO animated:YES];
}
NOTE:
Setting the cell's selected property = NO and animated = YES with the above method will cause the separator to disappear. The only way I've found to circumvent this is to set animated = NO but, if I find another way I will update my answer.