UITableView change image on cell select and reset others - ios

I'd like to change a UIImage which is inside a UITableViewCell when the user selects the row. Thats now too dificult. I can do this in didSelectRowAtIndex just fine. However, and heres the problem, I want the other cells (each cell has standard image) to have the standard image again. (If the cells have the standard image again, the selected image should be "marked" (meaning the non-marked image will be replaced by the marked image, which I already have the code for)
See it as a Checkbox that you know from HTML.
Here is my attempt:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView cellForRowAtIndexPath:indexPath];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:YES];
//Little flashing animation
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[UIView animateWithDuration:2.0f animations:^{
} completion:^(BOOL finished) {
;
}];
//Mark the selected cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
ALog(#"%i", cell.imageView.tag);
ALog(#"%i", [[[tableView cellForRowAtIndexPath:indexPath] imageView] tag]);
UIImageView *iconimgView = (UIImageView *)[[tableView cellForRowAtIndexPath:indexPath] viewWithTag:TAG_IMAGEMARKERCELL];
[iconimgView setImage:[UIImage imageNamed:#"circle-answer-marked.png"]];
//..
}
The UIImageView is defined here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//Add this to cell only once, not everytime a cell is displayed! (Everyhing goes in here)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
[[cell textLabel] setNumberOfLines:0]; // unlimited number of lines
[[cell textLabel] setLineBreakMode:NSLineBreakByWordWrapping];
[[cell textLabel] setFont:[UIFont fontWithName:#"PTSans-Regular" size:33 / 2]];
[[cell textLabel] setTextColor:[self colorFromHexString:COLOR_DEFAULT_TEXT_COLOR]];
cell.indentationLevel = cell.indentationLevel + 2;
// //Marker image
imgCell_Marker = [[UIImageView alloc]initWithFrame:CGRectMake(10, 22, 20, 20)];
imgCell_Marker.image=[UIImage imageNamed:#"circle-answer.png"];
imgCell_Marker.tag = TAG_IMAGEMARKERCELL;
ALog(#"%#", imgCell_Marker);
[cell.contentView addSubview:imgCell_Marker];
}
//..
return cell;
}
Odd thing is, the UIImageViews have a predefined tag but if I want to get my hands on that in the didSelectRowAtIndexPath its always "0". (the default value of the tag)
Thanks in advance.

Use this block of code:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView reloadData];
UITableViewCell *cell = (UITableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:#"image.png"];
}
At first, you set all of your cells to their default condition, and then you change the image of your current cell.

You have issues on a number of fronts.
First, the information which determines what image should be displayed should be part of your model. So, when a row is selected, set a flag in your model to say that this item is tagged. At the same time, find the other items that are tagged and untag them. Now, reload the rows that have changed. In cellForRowAtIndexPath, update the requested cells to set the standard or the alternative image based on the tag info from the model.
Second, for your use of tag - you are getting mixed up between imgCell_Marker and imageView. When you do:
ALog(#"%i", [[[tableView cellForRowAtIndexPath:indexPath] imageView] tag]);
you are querying the default imageView, so the tag will always be zero. You should be using viewWithTag:TAG_IMAGEMARKERCELL to find the actual image view you want.

From attribute inspector, set accessory as "Check Mark" for your prototypeCell. This would solve your issue. No need to change image or anything. let me know if this is not what you want

Make you life easy. Use UITableViewCell::selectedBackgroundView to pre set the content for selected cellĀ“s.

NOTE: this is perfect in my case, so you probably dont want to use it in your case (or let me explain you why you should when you're in a similar position as me)
The code would look like that now:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
[[cell textLabel] setNumberOfLines:0]; // unlimited number of lines
[[cell textLabel] setLineBreakMode:NSLineBreakByWordWrapping];
[[cell textLabel] setFont:[UIFont fontWithName:#"PTSans-Regular" size:33 / 2]];
[[cell textLabel] setTextColor:[self colorFromHexString:COLOR_DEFAULT_TEXT_COLOR]];
cell.indentationLevel = cell.indentationLevel + 2;
//Marker image
imgCell_Marker = [[UIImageView alloc]initWithFrame:CGRectMake(10, 22, 20, 20)];
imgCell_Marker.image=[UIImage imageNamed:#"circle-answer.png"];
imgCell_Marker.tag = TAG_IMAGEMARKERCELL;
[cell.contentView addSubview:imgCell_Marker];
//.. (more data here, just snipped it)
return cell;
}
Here is why I am using this:
I know that my array from where the data for the UITableView comes from is only at top 5 items long. Therefore I can simply delete the if statement in my cellForRowAtIndexPath method of my UITableView. It wont hurt my app (or waste cpu time) because there is so little to do, no know will know.
Still, this solution is kinda ugly. But its okay (I guess) in this case

Related

UITableView with UISwitch

I use storyboard and Auto Layout. I add UISwitch to my cell with tag 5. When I choose first UISwitch and scroll down I see that other UISwitch is also turned on and if I scroll up my first UISwitch is turned off. How to fix this?
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UISwitch* switchView = (UISwitch *)[cell viewWithTag:5];
[switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
return cell;
}
This is because UITableView reuse UITableViewCell so one cell can be use more than once in different indexPaths, in this situation its your responsibility to maintain the state of UITableViewCell subViews. Better place to do this is cellForRowAtIndexPath where you are returning cell add logic to make show/hide UISwitch or to select accurate state i.e. on or off, you can keep that flag in dataSource object and then you can check for that flag to make set right state for UISwitch
Try This:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellSetting";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [self.settingsArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if ([[self.settingsArray objectAtIndex:indexPath.row] isEqualToString:ROW_PRIVATE_BROWSING])
{
self.privateBrowsingSwitch =[[UISwitch alloc]initWithFrame:CGRectMake(cell.frame.size.width-65, 10, 30, 30)];
if (ApplicationDelegate.privateBrowsing)
{
[self.privateBrowsingSwitch setOn:YES animated:YES];
}
[self.privateBrowsingSwitch addTarget:self action:#selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:self.privateBrowsingSwitch];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Every time cellForRowAtIndexPath is called you have to replace the specific data that needs to be displayed for a cell at that position. This includes things like labels, images and your UISwitch.
This occurs because UITableViews use a small number of cells that are reused.
In cellForRowAtIndexPath add something like this:
switchView.on = [self isSwitchOnForCellAtIndexPath:indexPath]
Then write whatever logic is required to determine if the switch should be on or not.

UITableView disappearing content

As soon as the table view gets touched the cell titles (and on-tap actions) disappear. I only use standard table view cells and store the values in an array. After the values disappear the table stays scrollable. Any ideas?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = [[systeme objectAtIndex:indexPath.row] description];
cell.backgroundColor = [UIColor clearColor];
[cell.textLabel setTextColor:[UIColor whiteColor]];
[cell.textLabel setTextAlignment:NSTextAlignmentCenter];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:#"choseSystem" object:[systeme objectAtIndex:indexPath.row]];
}
You should be sure that the reuse identifier is the same for all cells if you use only one type of cells. You should do something similar to the following in the portion of your code where to retrieve a reusable cell:
NSString *CellIdentifier = [NSString stringWithFormat:#"CellReuseIdentifier", (long)indexPath.section];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
And make you you set the #"CellReuseIdentifier" in your xib file or your storyboard.
If you would like to use multiple custom cells for a table view you should do something similar to what you're doing, but take into account that reuse identifiers need to be configured for every type of cells.
Hope this helps!
The table view was fine. I just added its view as a subview to another view without keeping reference to the actual UITableViewController. That was the problem.

DCRoundSwitch as Accessory

I'm creating an ios app where I want to use a switch as the accessory for a tableview. I've found the following sample of how to use a UISwitch as the accessory: http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/ManageSelections/ManageSelections.html (see "Responding to Selections" section).
What I'd like to do is to use a DCRoundSwitch (https://github.com/domesticcatsoftware/DCRoundSwitch) instead of a UISwitch so I can customize the text. But when I create the accessory in the way that is suggested by the sample code, I just get the round knob, I don't get the whole switch. The code I'm using to add the accessory is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"PersonCell";
MyPerson *person = [self.dataController objectInListAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
DCRoundSwitch *switchObj = [[DCRoundSwitch alloc] initWithFrame:CGRectMake(1.0, 1.0, 20.0, 20.0)];
switchObj.onText = #"in";
switchObj.offText = #"out";
[switchObj addTarget:self action:#selector(personIn:) forControlEvents:(UIControlEventValueChanged | UIControlEventTouchDragInside)];
cell.accessoryView = switchObj;
[[cell textLabel] setText:person.name];
[[cell detailTextLabel] setText:person.label];
return cell;
}
What can I do to make the DCRoundSwitch work as a TableView accessory?
Thanks!
I think you width is just to narrow -- try something like 60 or 70 for the width (the default width for a UISwitch in the storyboard is 79).

tableview with checkmark and detail disclosure together

I'm making a tableview with multiple row selected option. So, I used the checkmark accessory type action. I also require to edit/rename the text in the selected row.
Basically, I need to put checkmark (checkbox) on the left side and detail disclosure on the right side of the cell, both functional.
Below code is for checkmark that i have, currently checkmark appears on the right side of the cell.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
TSIPAppDelegate *appDelegate = (TSIPAppDelegate *)[[UIApplication sharedApplication]delegate];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
if (cell.accessoryType==UITableViewCellAccessoryNone)
{
cell.accessoryType=UITableViewCellAccessoryCheckmark;
appDelegate.selectedFile = cellText;
if (prevSP!=indexPath.row) {
cell=[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:prevSP inSection:0]];
cell.accessoryType=UITableViewCellAccessoryNone;
prevSP=indexPath.row;
}
}
else if (prevSP!=indexPath.row){
cell.accessoryType=UITableViewCellAccessoryNone;
}
}
Any suggestions, please?
When a row selected, checkmark should be enabled/disabled AND disclosure button selected, it should open a new view for editing the selected row.
accessoryType type is of enum UITableViewCellAccessoryType, by definition it will not accept multiple values as it not bitwise enum. So, you have to choose one and mimic the other by custom code.
I'd recommend using the UITableViewCellAccessoryCheckmark accessory type on the tableview and adding a "Detail Disclosure" button to the cell. Unfortunately you can't do exactly what you're looking for, but this is the cleanest alternative approach that I've found.
This is sample code which i have used in one of my app
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text=[NSString stringWithFormat:#"%#",[cellarray objectAtIndex:indexPath.row]];
cell.textLabel.textColor=[UIColor blackColor] ;
cell.textLabel.tag=indexPath.row;
cell.textLabel.font=[UIFont fontWithName:#"HelveticaNeue-Bold" size:15];
// cell.textLabel.highlightedTextColor=[UIColor colorWithRed:242.0f/255.0f green:104.0f/255.0f blue:42.0f/255.0f alpha:1] ;
cell.selectionStyle=UITableViewCellSelectionStyleNone;
}
UIImageView *ima=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"tick.png"]];
ima.frame=CGRectMake(280, 15, 14, 14);
ima.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleRightMargin;
int row = [indexPath row];
//cell.accessoryType = (row == selectedRow) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.textLabel.textColor= (row == selectedRow) ? [UIColor colorWithRed:242.0f/255.0f green:104.0f/255.0f blue:42.0f/255.0f alpha:1] : [UIColor blackColor] ;
if (row==selectedRow) {
[cell.contentView addSubview:ima];
}
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Background.png"]];
[tempImageView setFrame:tableView.frame];
tableView.backgroundView = tempImageView;
[tempImageView release];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
selectedRow = [indexPath row]; // selected row is of type int declared in .h
[tableView reloadData];
}
This code will have only one checkmark in entire tableView.. You can modify it to have multiple checkmark in that
Hope this helps !!!

Why can't I set an image to my UITableViewCell?

I created an option menu using a UITableViewController and can get the labels to set correctly, but not the images.
I tried taking out the switch statement and using an array filled with the correct values based on [indexPath row] and could not get it to work correctly either.
Any ideas?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier];
}
switch ([indexPath row]) {
case 0:
[[cell imageView] setImage:[UIImage imageNamed:#"42-photos.png"]];
[[cell textLabel] setText:#"Photos"];
break;
case 1:
[[cell imageView] setImage:[UIImage imageNamed:#"280-clapboard.png"]];
[[cell textLabel] setText:#"Videos"];
break;
case 2:
[[cell imageView] setImage:[UIImage imageNamed:#"42-info.png"]];
[[cell textLabel] setText:#"About"];
break;
default:
return cell;
break;
}
return cell;
}
The UITableViewCellStyleValue2 doesn't include the image:
A style for a cell with a label on the left side of the cell with text
that is right-aligned and blue; on the right side of the cell is
another label with smaller text that is left-aligned and black. The
Phone/Contacts application uses cells in this style.
You should use UITableViewCellStyleDefault instead (or design your own cell).
You have not created a custom cell i guess , it's better to have a custom cell if you have so many controls in your UITableViewCell and then accessing the property to the controls you can change the image.you can refer this post of mine.Your style chosen will not support image.

Resources