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).
Related
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.
I want to move the position of the title textview in my cell prototype. When I select the "Title" I cannot adjust the X,Y coordinates or even the Width and Height. Are we not allowed to customize this part of the cell.
When I tried to do this in code it said I was not allowed to access the current parameter. How do I move the location of this title and subtitle. I want to move it to the top of the cell and have my colored views below. Thanks in advance, still somewhat new to Xcode.
cell.textLabel.frame.origin.x = 30; //not allowed to access
you cannot access to the x position, but you can put the whole frame easily.
Here and example all by code, I think It's your best option:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"reuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
cell.textLabel.frame = CGRectMake(0, 0, cell.frame.size.width, 30);
cell.textLabel.backgroundColor = [UIColor greenColor];
}
// Configure your cell...
return cell;
}
Here using Story cell, I think is worse because more work.(It didn't take advantage for the reuse technology at all).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"storyIdentifier" forIndexPath:indexPath];
cell.textLabel.frame = CGRectMake(0, 0, cell.frame.size.width, 30);
cell.textLabel.backgroundColor = [UIColor greenColor];
// Configure your cell...
return cell;
}
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.
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
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 !!!