Probably a simple fix.
I've got an image inside each cell of my table view controller and a tap gesture recognizer on it. That's working fine and logging appropriately.
What I need is for the image to change from its default state to then toggle between a "selected" state (green) and a "deselected" state (red). In other words, it's a checklist that's gray at first, then you tap the image, the image turns to a green checkmark, tap again, it turns to a red x.
Here's the catch: Had this working when it was only a matter of a conditional statement in the didSelectRowAtIndexPath method, but since I added the gesture recognizer and created the imageTapped method, I can't seem to translate it over. Therefore, otherwise helpful threads like this don't work for me.
Thanks as always. You guys are the best.
Here's the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PlacesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"PlacesCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//Create ImageView
cell.imageView.image = [UIImage imageNamed:#"checkmark.png"];
//Add Gesture Recognizer
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped)];
tapped.numberOfTapsRequired = 1;
[cell.imageView addGestureRecognizer:tapped];
cell.imageView.userInteractionEnabled = YES;
[cell addSubview:cell.imageView];
return cell;
}
//Method controlling what happens when cell's UIImage is tapped
-(void)imageTapped
{
UITableViewCell *cell;
UIImage *imageDefault = [UIImage imageNamed:#"checkmark.png"];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
if (cell.imageView.image == imageDefault) {
cell.imageView.image = imageGreen;
cell.selected = true;
NSLog(#"Selected");
} else {
cell.imageView.image = imageRed;
cell.selected = false;
NSLog(#"Deselected");
}
}
i have modified your code , check it
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PlacesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"PlacesCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//Create ImageView
cell.imageView.image = [UIImage imageNamed:#"checkmark.png"];
//Add Gesture Recognizer
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
tapped.numberOfTapsRequired = 1;
[cell.imageView addGestureRecognizer:tapped];
cell.imageView.userInteractionEnabled = YES;
//[cell addSubview:cell.imageView];
return cell;
}
//Method controlling what happens when cell's UIImage is tapped
-(void)imageTapped:(UIGestureRecognizer*)gesture
{
UIImageView *selectedImageView=(UIImageView*)[gesture view];
UIImage *imageDefault = [UIImage imageNamed:#"checkmark.png"];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
if (selectedImageView.image == imageDefault) {
selectedImageView.image = imageGreen;
//cell.selected = true;
NSLog(#"Selected");
} else {
selectedImageView.image = imageRed;
//cell.selected = false;
NSLog(#"Deselected");
}
}
Related
I have a custom cell with imageview and label.When user selected a particular cell in the tableview I want change the image color or tint.
I managed to change the color of the label , but dont know how to do with the image. Any ideas?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MenuCell";
MenuTableViewCell *cell = (MenuTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MenuTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
// cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.lblTitle.text = [[_items objectAtIndex:[indexPath row]] valueForKey:#"title"];
cell.imgIcon.image = [UIImage imageNamed:[[_items objectAtIndex:[indexPath row]] valueForKey:#"image"]];
cell.lblTitle.highlightedTextColor = [UIColor colorWithRed:0.839 green:0.682 blue:0.047 alpha:1];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
return cell;
}
Thanks
You should be changing the cell data inside your MenuTableViewCell custom class. There will be a methods in there that control the selected, highlighted state. The method will look something like this example,
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
//Change the text colour & image
} else {
//Change it back to whatever is was
}
}
If you want to change cell image when you selected a cell. You can draw current image with a tintColor. See below code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MenuTableViewCell *cell = (MenuTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
// Change cell image color
UIImage * image = [cell.imgIcon.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
cell.imgIcon.image = image;
cell.imgIcon.tintColor = [UIColor redColor]; // Your tint color
[cell.imgIcon tintColorDidChange];
}
Hope that helps!
In the method tableviewDidSelectRowAtIndexPath write this code
//Edited to the correct syntax
{
MenuTableViewCell *cell = (MenuTableViewCell *)[tableview cellForRowAtIndexPath:indexPath];
cell.image = [UIImage imageNamed:#"your image name when you want to change to selected"];
}
The correct syntax is the following:
In the method tableviewDidSelectRowAtIndexPath
MenuTableViewCell *cell = (MenuTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.imgIcon.image = [UIImage imageNamed:#"your image name when you want to change to selected"];
Saheb Roy's answer put me on the right track but cellAtIndexPath has to be replaced by cellForRowAtIndexPath.
EDITED: in the above code what was being done was to have two different images and change them depending on whether the cell was selected or not.
Combining the answers given by Saheb Roy, longpham and Devster101 finally i added the following code in custom cell class MenuTableViewCell.m:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
UIImage * image = [_imgIcon.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_imgIcon.image = image;
_imgIcon.tintColor = [UIColor colorWithRed:0.839 green:0.682 blue:0.047 alpha:1];
[_imgIcon tintColorDidChange];
} else {
UIImage * image = [_imgIcon.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_imgIcon.image = image;
_imgIcon.tintColor = [UIColor blackColor];
[_imgIcon tintColorDidChange];
}
}
I am trying to animate a UIImageview in a "table view cell", but the image never shows.
Here is the code I'm trying to use.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
cell.textLabel.font = [UIFont systemFontOfSize:16.0];
}
if (cell)
{
cell.textLabel.text = [titleArray objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor darkGrayColor];
UIImage *musicOne = [UIImage imageNamed:#"music1.png"];
UIImage *musicTwo = [UIImage imageNamed:#"music2.png"];
UIImage *musicThree = [UIImage imageNamed:#"music3.png"];
NSArray *imagesArray = [NSArray arrayWithObjects:musicOne, musicTwo, musicThree, nil];
if (indexPath.row == 0)
{
cell.imageView.animationImages = imagesArray;
cell.imageView.animationDuration = 1.0f;
cell.imageView.animationRepeatCount = 0;
[cell.imageView startAnimating];
}
}
return cell;
}
The image shows in the cell if I don't try to do animations with several images and just use one image in the image view.
cell.imageView.image = [imagesArray objectAtIndex:0];
It is necessary to set image property of cell.imageView too along with animationImages, otherwise UITableViewCell will show nothing.
In order to improve performance of the app and to save memory do following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:#"music1.png"];
return cell;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
UIImage *musicOne = [UIImage imageNamed:#"music1.png"];
UIImage *musicTwo = [UIImage imageNamed:#"music2.png"];
UIImage *musicThree = [UIImage imageNamed:#"music3.png"];
NSArray *imagesArray = #[musicOne, musicTwo, musicThree];
[cell.imageView setAnimationImages:imagesArray];
cell.imageView.animationDuration = 1.0f;
[cell.imageView startAnimating];
}
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cell.imageView stopAnimating];
[cell.layer removeAllAnimations];
}
Try give the imageView a tag (e.g. 1) then get the image view like this:
UIImage *musicOne = [UIImage imageNamed:#"music1.png"];
UIImage *musicTwo = [UIImage imageNamed:#"music2.png"];
UIImage *musicThree = [UIImage imageNamed:#"music3.png"];
NSArray *imagesArray = [NSArray arrayWithObjects:musicOne, musicTwo, musicThree, nil];
if (indexPath.row == 0)
{
UIImageView *imageView = (UIImageView *)[cell viewWithTag:1];
imageView.animationImages = imagesArray;
imageView.animationDuration = 1.0f;
imageView.animationRepeatCount = 0;
[imageView startAnimating];
}
This exact same code worked for me. I know in UIScrollView animations will stop when view is scrolling and for that reason you should use CADisplayLink to run you animation on NSRunLoopCommonModes instead of on NSDefaultRunLoopMode, but I have tested your code and it worked.
I have 3 sections in a table view and only using the middle section, section 2, to show various cells. Sections 1 and 3 only show one cell and I am making them unclickable since I want to display buttons and text on them. I made them and it was working fine until I made sections 1 and 3 userInteractionEnabled=NO.
Code: I know I can make this Object Oriented, and it was, but once this problem came up I tried to make it differently but it is still the same.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
UIView *selectedBackgroundView = [[UIView alloc] initWithFrame:CGRectZero];
selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.1];
cell.selectedBackgroundView = selectedBackgroundView;
if(cell==nil) { NSLog(#"Cell is nil");}
}
if(indexPath.section == 0)
{
cell.textLabel.text = nil;
cell.accessoryView = nil;
cell.detailTextLabel.text = nil;
dosageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
amountButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[dosageButton addTarget:self action:#selector(showDosages:) forControlEvents:UIControlEventTouchUpInside];
[amountButton addTarget:self action:#selector(showAmount) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:dosageButton];
[self.view addSubview:amountButton];
cell.userInteractionEnabled = NO;
return cell;
}
else if (indexPath.section == 1)
{
if (self.nameMutable.count != 0 )
{
cell.textLabel.text = [self.nameMutable objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#",[self.priceMutable objectAtIndex:indexPath.row]];
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"chevron"]];
return cell;
}
else
{
//Empty for now. Waiting for data fetching to finish
return cell;
}
}
else if (indexPath.section == 2)
{
cell.userInteractionEnabled = NO;
cell.accessoryView = nil;
cell.detailTextLabel.text = nil;
return cell;
}
else
{
NSLog(#"Something went wrong");
return cell;
}
}
For some reason my table view cell in section 1 where it is supposed to be clickable the color changes to a dark grey and is not clickable anymore. Its usually cell 3 and cell 10. Also, when I scroll down and Section 0 is no longer visible and then I scroll back up and Section 0 is visible, some of the cells become non-clickable and the color of the text changes.
Also, how can I make a certain cell, inside section 1, have bigger height because the text is too long to display and it starts to display "..." or covers the detailTextLabel. Thanks in advance.
You have to remember that these cells are being reused or 'recycled' so if you're setting userInteractionEnabled=NO for an if statement you need to set it to userInteractionEnabled=YES in your else statement, or set it as YES before all your statements. You also want to make sure that you're adding any other subviews (buttons etc.) that are unique to certain index paths to cells that are newly created, where you would stick that piece of code inside your if(cell==nil) statement. Something like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
UIView *selectedBackgroundView = [[UIView alloc] initWithFrame:CGRectZero];
selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.1];
cell.selectedBackgroundView = selectedBackgroundView;
if(indexPath.section == 0) {
dosageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
amountButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[dosageButton addTarget:self action:#selector(showDosages:) forControlEvents:UIControlEventTouchUpInside];
[amountButton addTarget:self action:#selector(showAmount) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:dosageButton];
[self.view addSubview:amountButton];
}
if(cell==nil) { NSLog(#"Cell is nil");}
}
cell.userInteractionEnabled = YES;
cell.accessoryView = nil;
cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
if(indexPath.section == 0)
{
cell.userInteractionEnabled = NO;
}
else if (indexPath.section == 1)
{
if (self.nameMutable.count != 0 )
{
cell.textLabel.text = [self.nameMutable objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#",[self.priceMutable objectAtIndex:indexPath.row]];
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"chevron"]];
}
else
{
//Empty for now. Waiting for data fetching to finish
}
}
else if (indexPath.section == 2)
{
cell.userInteractionEnabled = NO;
}
else
{
NSLog(#"Something went wrong");
}
return cell;
}
And if you want to change the height of certain index paths (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath Docs delegate method.
I have a UITable that reuses cells. Each cell has an image dependant on a condition. The correct images are always used however when cells are reused the old image is displayed behind the new one. I have tried to remove the uiimageview before adding a new subview however it has no effect.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
return cell;
}
Any help would be greatly appreciated?
The problem is each time cellForRowAtIndexPath: is called you create a new imageview.
I corrected your code as follows:
Here we create an imageView once for each new new cell and replace it's image every time cellForRowAtIndexPath: is called:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
UIImageView *achievImg = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
//New Cell ... Create Image view
achievImg = [[UIImageView alloc] init];
achievImg.tag = 10;
[cell.contentView addSubview:achievImg];
}
else{
//Old cell...get previously createdd imageview
achievImg = (UIImageView*)[cell.contentView viewWithTag:10];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
//You don't need this because it doesn't have a superview in the first place..it's new
//[achievImg removeFromSuperview];
return cell;
}
try like this,
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
}
return cell;
}
You are always adding the imageView to the contentView of the cell. If the cell is reused that will lead to multiple imageViews in cell.
You can give a tag to the imageView. Always check if there is a view will same tag in the contentView of cell. If not add the imageView.
UIImageView *achievImg = (UIImageView *)[cell.contentView viewWithTag:55];
if(!achievImg){
achievImg = [[UIImageView alloc] init];
achievImg.tag = 55;
[cell.contentView addSubView:achievImg];
}
I want to display an image over a cell upon selection. I've tried endless ways to do so without succes.
I've tried adding this to didSelectRowAtIndexPath:
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.imageView.image = [UIImage imageNamed:#"deselected_image.png"];
cell.imageView.highlightedImage = [UIImage imageNamed:#"selected_image.png"];
But the image won't change upon push.
Thanks
The code you have is creating a new table view cell - you need to retrieve the current cell that was selected. Try the following instead:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:#"deselected_image.png"];
cell.imageView.highlightedImage = [UIImage imageNamed:#"selected_image.png"];
}
I have applied the UIColor to each cell on request.You can replace the UIColor code & apply the image.
Here is my code
- (void)tableView: (UITableView*)tableView willDisplayCell: (UITableViewCell*)cell forRowAtIndexPath: (NSIndexPath*)indexPath
{
if(tableView==tblLanguage)
{
cell.backgroundView = [[UIView alloc] init];
((UIView *)cell.backgroundView).backgroundColor = !(indexPath.row % 2)?[UIColor colorWithRed:(float)231/255 green:(float)231/255 blue:(float)231/255 alpha:1.0]:[UIColor colorWithRed:(float)218/255 green:(float)218/255 blue:(float)218/255 alpha:1.0];
((UIView *)cell.backgroundView).alpha=1.0;
//ilangSelectedIndex is set in the didselect row of the tableview delegate function
if(ilangSelectedIndex==[indexPath row])
{
((UIView *)cell.backgroundView).backgroundColor=[UIColor colorWithRed:(float)171/255 green:(float)177/255 blue:(float)213/255 alpha:1.0];
}
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
}
}
In the Did select function of the table you set the ilangSelectedIndex as Indexpath.row of your table & reload the table to see the effect.
Try this code in didSelectRowAtIndexPath:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selectedBackgroundView=[[UIImageView alloc]init];
cell.backgroundView =[[UIImageView alloc] init];
((UIImageView *)cell.selectedBackgroundView).image=[UIImage imageNamed:#"selected.png"];