some time ago someone already asked this question and a few answers were given but i didn't really understand any of them. So i was wondering if anyone could please write an easy to understand tutorial on how to do the things shown on the image below:
http://img208.yfrog.com/img208/6119/screenshotkmr.png
I would be so greatful if anyone can share exactly how to this because it looks really cool and i would love to use something similar in my application :-)!
Make a unchecked and checked image..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if ([selectedRowsArray containsObject:[contentArray objectAtIndex:indexPath.row]]) {
cell.imageView.image = [UIImage imageNamed:#"checked.png"];
}
else {
cell.imageView.image = [UIImage imageNamed:#"unchecked.png"];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleChecking:)];
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES; //added based on #John 's comment
//[tap release];
cell.textLabel.text = [contentArray objectAtIndex:indexPath.row];
return cell;
}
- (void) handleChecking:(UITapGestureRecognizer *)tapRecognizer {
CGPoint tapLocation = [tapRecognizer locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
if ([selectedRowsArray containsObject:[contentArray objectAtIndex:tappedIndexPath.row]]) {
[selectedRowsArray removeObject:[contentArray objectAtIndex:tappedIndexPath.row]];
}
else {
[selectedRowsArray addObject:[contentArray objectAtIndex:tappedIndexPath.row]];
}
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tappedIndexPath] withRowAnimation: UITableViewRowAnimationFade];
}
One of the way I can think of is you do custom UITableViewCell (this tutorial is good for starting. This is another, similar one). Inside the custom UITableViewCell you need to put a UIButton there with a circle image. When user select the button, you change the image to the green circle
Related
Edit:
Thanks everyone, but this has gotten to be too general as it is clear there are deeper issues at hand. I'm going to try to delete this question. I appreciate all of your help!
We have a large UITableViewCell with a UILabel inside and we want to detect the user's single tap or touch on that label. We're adding a UITapGestureRecognizer inside of our subclassed UITableViewCell:
CGRect frame = CGRectMake(0, 10, 150, 20);
self.titleLabel = [[UILabel alloc] initWithFrame:frame];
self.titleLabel.text = self.title;
self.titleLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(expandButtonTapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self.titleLabel addGestureRecognizer:singleTap];
[cell.contentView addSubview:self.titleLabel];
We've also tried setting the target to the cell's UITableViewController, but same result, the action doesn't get performed. When checking the debugger, the gesture is indeed there and attached to the label.
Edit: After more investigating, if we add a normal UIButton to the cell, it cannot be clicked. Doing more investigating, but here is the cellForRowAtIndexPath method:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (![self.metaDataSections count]) {
return nil;
}
ACMTableCellMetaData *metaData = [self metaDataForIndexPath:indexPath];
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:metaData.reuseIdentifier];
if (cell == nil) {
cell = [metaData createCell];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell = [metaData updateCellWithCellForReuse:cell];
return cell;
}
The createCell method:
- (UITableViewCell *)createCell
{
UITableViewCell *cell = [super createCell];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:self.reuseIdentifier];
cell.frame = CGRectMake(CGRectGetMinX(cell.contentView.frame),
CGRectGetMinY(cell.contentView.frame),
CGRectGetWidth(cell.contentView.frame),
ACM_TABLE_CELL_HEIGHT);
[self setupExpandButtonInCell:cell];
}
return cell;
}
updateCell method:
- (UITableViewCell *)updateCellWithCellForReuse:(UITableViewCell *)cell {
UILabel * titleLabel = (UILabel *)[cell.contentView viewWithTag:TITLE_TAG];
titleLabel = self.titleLabel;
self.cell = [super updateCellWithCellForReuse:cell];
return self.cell;
}
I clipped out some code that I don't believe affects anything. The didSelectRowAtIndexPath that is being over ridden in the the subclassed tableview doesn't have anything that would prevent user taps. But strangely, if I put a break point there, it never gets hit when tapping the cells. So I believe there are other issues at play here. We can't see why this is the case however.
If you are writing this code in class, which inherits UITableViewCell, then instead of
[cell.contentView addSubview:self.titleLabel];
use
[self addSubView:self.titleLabel];
make sure to implement
-(void)expandButtonTapped:(parameter type)parameter{
}
in the same class.
I forgot to mention about
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
cell = [[TableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
// Configure the cell...
return cell;
}
I am new in iOS
I am creating dynamically buttons in my tableview
i had set a image on button for check and uncheck
What i have to do is when i tap(or check) on button the data on indexpath row will add in my array.
And if i deselect it , data removes from my array. Please Help me
-(void)btnForCheckBoxClicked:(id)sender
{
UIButton *tappedButton = (UIButton*)sender;
indexForCheckBox= [sender tag];
if([tappedButton.currentImage isEqual:[UIImage imageNamed:#"checkbox_unchecked.png"]])
{
[sender setImage:[UIImage imageNamed: #"checkbox_checked.png"] forState:UIControlStateNormal];
strinForCheckBox= [ApplicationDelegate.ArrayForSearchResults objectAtIndex:indexForCheckBox];
[arrForCheckBox addObject:strinForCheckBox];
NSLog(#"Sender Tag When Add %d", indexForCheckBox);
NSLog(#"Array Count Check Box %d",[arrForCheckBox count]);
}
else
{
[sender setImage:[UIImage imageNamed:#"checkbox_unchecked.png"]forState:UIControlStateNormal];
[arrForCheckBox removeObjectAtIndex:indexForCheckBox];
NSLog(#"Sender Tag After Remove %d", indexForCheckBox);
NSLog(#"Array Count Uncheck Box %d",[arrForCheckBox count]);
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if ([selectedRowsArray containsObject:[contentArray objectAtIndex:indexPath.row]) {
cell.imageView.image = [UIImage imageNamed:#"checked.png"];
}
else {
cell.imageView.image = [UIImage imageNamed:#"unchecked.png"];
}
UITapGestureRecogniser *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleChecking:)
[cell.imageView addGestureRecognizer:tap];
[tap release];
cell.textLabel.text = [contentArray objectAtIndex];
return cell;
}
- (void) handleChecking:(UITapGestureRecognizer *)tapRecognizer {
CGPoint tapLocation = [tapRecognizer locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
if (selectedRowsArray containsObject:[contentArray objectAtIndex:tappedIndexPath.row]) {
[selectedRowsArray removeObject:[contentArray objectAtIndex:tappedIndexPath.row]];
}
else {
[selectedRowsArray addObject:[contentArray objectAtIndex:tappedIndexPath.row]];
}
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tappedIndexPath] withRowAnimation: UITableViewRowAnimationFade];
}
I think this question has been answered some time ago! Check it out first and tell us if this is what you are looking for ?
How to add checkboxes to UITableViewCell??
image http://img208.yfrog.com/img208/6119/screenshotkmr.png
You can add this on your button click method.
First set Bool value which set yes on one click and No In second click and when you first click add that index value in array using array addobject property and other click removeobject property.
-(void)list
{
if(isCheck==YES)
{
//add array object here
isCheck=NO;
}
else if(isCheck==NO)
{
//remove array object here
isCheck=YES;
}
}
I have found another way. Code extracted from #The Saad And, i had just modified with key/value pairs as useful one like below code -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if ([[selectedRowsArray objectAtIndex:indexPath.row] containsObject:#"YES"])
cell.imageView.image = [UIImage imageNamed:#"checked.png"];
else
cell.imageView.image = [UIImage imageNamed:#"unchecked.png"];
UITapGestureRecogniser *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleChecking:)
[cell.imageView addGestureRecognizer:tap];
[tap release];
cell.textLabel.text = [contentArray objectAtIndex];
return cell;
}
- (void) handleChecking:(UITapGestureRecognizer *)tapRecognizer {
CGPoint tapLocation = [tapRecognizer locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
if ([[selectedRowsArray objectAtIndex:tappedIndexPath.row] containsObject:#"YES"])
[selectedRowsArray replaceObjectAtIndex:tappedIndexPath.row withObject:[NSSet setWithObject:#"NO"]];
else
[selectedRowsArray replaceObjectAtIndex:tappedIndexPath.row withObject:[NSSet setWithObject:#"YES"]];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tappedIndexPath] withRowAnimation: UITableViewRowAnimationFade];
}
Add, the objects for selectedRowsArray as below with the count of your self.tableView's row count. So, you need to add the bool values as below
for ( int i = 0; i < tableViewRowCount; i++ ) { // tableViewRowCount would be your tableView's row count
....
....
....
[selectedRowsArray addObject:[NSSet setWithObject:#"NO"]];
....
....
}
Hope this helps! Cheers!
Update
With the use of updated code you don't need to keep key/value pair of NSMutableDictionary for overkilling that. NSSet provides you better way with this.
Hey guys i have a table view that can add and delete cells. but when i delete the only cell that comes with the app, and i try to add a new cell with the text of "Meghan Way" and the text just automatically changes it self to the original cells text which is "House 1" here is my code!
- (IBAction)saveButton:(id)sender {
FacePlatesViewController * viewController = (FacePlatesViewController
*)self.parentViewController;
[viewController addObject:[NSMutableDictionary dictionaryWithObject:text.text
forKey:#"name"]];
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)cancel:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = [[cells objectAtIndex:indexPath.row] valueForKey:#"name"];
UIImage * myimage = [UIImage imageNamed: #"check.png"];
image = [[UIImageView alloc]initWithImage:myimage];
tableView.backgroundColor = [UIColor clearColor];
self.myTableView = tableView;
}
return cell;
}
this is for the save button! any help would be very appreciated:D Thanks
You code is quite messed up. I have improved it below and added comments:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
} //The if block should end here. You should set the cell's label irrespective whether the cell was nil. This is the cause of the issue you are facing.
cell.textLabel.text = [[cells objectAtIndex:indexPath.row] valueForKey:#"name"];
//You are doing nothing with the UIImage
//UIImage * myimage = [UIImage imageNamed: #"check.png"];
//image = [[UIImageView alloc]initWithImage:myimage];
//You should be setting the background color just once, in ViewDidLoad, not here.
//tableView.backgroundColor = [UIColor clearColor];
//I don't see why this is required
//self.myTableView = tableView;
return cell;
}
Are you storing the text labels for these cells in any kind of array or dictionary and loading them in there using the standard "cellForRowAtIndexPath?" If so, then you need to delete the dictionary / array entry in that data source to prevent it from being used again.
I can't tell for sure without seeing some more code...but it sounds like a cell recycling issue. I could be wrong...but I'd need to see more info.
I am having a problem setting a UIImageView or UIView on the cell of the Grouped table on the iPhone.
For this I am using this code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self.tableContents objectForKey:[self.sotreKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
if(indexPath.section == 1 && indexPath.row ==1)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 14, 40, 40)];
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"Back.png",nil]];
[cell.contentView addSubview:imageView];
[imageView release];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
But it is not placed on the cell . When ever I select the row it will display for that time only, what is the problem?
Does anyone have any idea what the problem is. I think the image is getting overwritten by the cell .
Thanks in advance
try making
cell.accessoryType = UITableViewCellAccessoryNone;
It seems that you are adding image on accessory view.
If yes, you can add cell.accessoryView = imageView;
I do have some ideas of what might be happening.
You are adding an image view to the contentView then you are setting the text of the textLabel which is a part of the contentView and is probably sitting on top of the image. Try this and see if you can at least see your image on the left side.
cell.imageView.image = [UIImage imageNamed:#"Back.png"];
Now when you dequeue cells you need to remember that all the views you added last time you created the cell are still there, so as you scroll you will just be stacking back buttons on top of each other.
Also the following line [tableView deselectRowAtIndexPath:indexPath animated:YES]; is dead code because it occurs after a return statement. You might want to place that in the delegate call – tableView:willDisplayCell:forRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self.tableContents objectForKey:[self.sotreKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
if(indexPath.section == 1 && indexPath.row ==1)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 14, 40, 40)];
imageView.image = [UIImage imageNamed:#"Back.png"];
[cell.contentView addSubview:imageView];
[imageView release];
}
cell.textLabel.text = [listData objectAtIndex:indexPath.row];
return cell;
}
Make sure that your image is named "Back.png" not "back.png" because the iOS on the phone is key sensitive.
In my tableView cell i have:
cell.imageView.image = image;
How can I detect the user click directly on that image, and not the cell.textLabel?
Add a UITapGestureRecognizer to the imageView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
/* ... */
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.imageView.image = /*...*/
UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)] autorelease];
[cell.imageView addGestureRecognizer:tapGesture];
cell.imageView.userInteractionEnabled = YES;
}
/* ... */
}
- (void)imageTapped:(UITapGestureRecognizer *)gesture {
UITableViewCell *cell = [[[gesture view] superview] superview];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForCell:cell];
NSLog(#"Image Tap %#", tappedIndexPath);
}
As some of the comments have pointed out, you should use an UIButton instead. A UIImageView is not designed to handle user interaction out of the box and it's much simpler to just create a button, add a target, and add it as a subview of the cell.