I'm trying to create a button in each tableviewcell and upon selected, the "Checked.png" should appear on the button.The default is "uncheck.png". However, the problem is the image always remain in "uncheck.png" regardless of the button being selected. It's driving me mad. Please help me on this. Would greatly appreciate if someone could provide some code snippets.Thank You
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TableCell" owner:self options:NULL];
cell = nibLoadedCell;
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(270.0, 10.0, 60.0, 60.0)];
[button setImage:[UIImage imageNamed:#"Uncheck.png"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"Checked.png"] forState:UIControlStateSelected];
[button addTarget:self action:#selector(Selected:) forControlEvents:UIControlEventTouchUpInside];
button.tag = indexPath.row;
[cell.contentView addSubview:button];
}
Look at the TouchCells example in XCode. Go to Help -> Developer Documenation and search TouchCells. Have a look at that sample project in XCode
As per documentation
For many controls, UIControlStateSelected state has no effect on behavior or appearance.
I think the same for UIButton also.
What I would suggest is you can set the button setImage property again to Checked.png in the didSelectRowAtIndexPath delegate of tableview.You should also set a unique tag for each button for identifying the button which you have to set the Checked.png Image.
Related
hi i am implementing a table in which i am getting request i have list of students to which i want to add as my room mate i have two button accept and reject the problem is here when i click on accept button i want that row will be deleted from the array and also i want to shift the deleted row value into the table of nextview controller in case of accept request . and in case of reject button cliked only want to delete the row not to move the value of cell into next view controller i am implementing this project by using storyboard can anybody have idea about that plase share me this is the code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DefaultCell"];
if(cell == nil) {
cell =[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"DefaultCell"];
}
acceptreq = [UIButton buttonWithType:UIButtonTypeRoundedRect];
acceptreq.frame =CGRectMake(170, 10, 60, 30);
rejectreq = [UIButton buttonWithType:UIButtonTypeRoundedRect];
rejectreq.frame =CGRectMake(240, 10, 60, 30);
[acceptreq setTitle:#"Accept" forState:UIControlStateNormal];
[rejectreq setTitle:#"Reject" forState:UIControlStateNormal];
[acceptreq addTarget:self action:#selector(Acceptrequest:) forControlEvents:UIControlEventTouchUpInside];
[rejectreq addTarget:self action:#selector(Rejectrequest:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:acceptreq];
[cell addSubview:rejectreq];
[acceptreq setTag:indexPath.row];
cell.textLabel.text = [myarray objectAtIndex:indexPath.row];
return cell;
}
In short you can delete selected Row with clicking UIbutton like bellow:-
-(IBAction)Acceptrequest:(id)sender
{
UIButton *btn =(UIButton*)sender;
[myarray removeObjectsAtIndexes:btn.tag];
[tableView deleteRowsAtIndexPaths:myarray withRowAnimation:UITableViewRowAnimationAutomatic];
[tableVIew reloadData];
}
You need to implement this method:
[tableView deleteRowsAtIndexPaths:arrayOfIndexPathsToDelete withRowAnimation:UITableViewRowAnimationAutomatic];
I add UIButton in the cell Dynamically
and change UIButton image on click of UIBarButtonItem
how i can change?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Display"] ;
[cell.textLabel setText:[NSString stringWithFormat:#"%#" ,[arrItemList objectAtIndex:indexPath.row]]];
UIButton *btnCheck = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnCheck.frame = CGRectMake(6.0f, 2.0f, 32.0f, 25.0f);
[btnCheck setTitle:#"" forState:UIControlStateNormal];
[btnCheck addTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:btnCheck];
return cell;
}
//Here IBAction for Bar Button Item
//when ever user click on BarButton then set the image of all btnCheck
-(IBAction)bbtnCheck:(id)sender
{
}
Assuming that your question is how to change the image of a button w/in every cell of your table when a bar button is clicked, I suggest the following:
Within tableView:cellForRowAtIndexPath, add:
btnCheck.tag = MY_BUTTON_TAG_NUMBER;
Then, when the bar button item is clicked, loop through the visible cells and use the button's tag to identify it and update its image.
-(IBAction)bbtnCheck:(id)sender {
for (UITableViewCell *cell in self.tableView.visibleCells) {
UIButton *button = [cell viewWithTag:MY_BUTTON_TAG_NUMBER];
[button setImage:[UIImage imageNamed:SOME_NEW_IMAGE] forState:UIControlStateNormal];
}
}
In that bbtnCheck you have to get the instance of that tableView (i.e. particular cell)..Then after you can get buttons added on that particular cell..
Please Check this....
-(IBAction)bbtnCheck:(id)sender
{
NSIndexPath *indexpath = [NSIndexPath indexPathForRow:YourRow inSection:YourSection]; // you have to set Row and Section according to your requirement
UITableViewCell *cellNew = [self.tblComments cellForRowAtIndexPath:indexpath];
for (UIButton *btn in [cellNew.contentView subviews])
{
if ([btn isKindOfClass:[UIButton class]])
{
[btn setImage:[UIImage imageNamed:#"yourImage.png"] forState:UIControlStateNormal];
}
}
}
I am making a simple timer app. I have a uitable with multiple rows. In that table I have put a UIButton. Everything works and so far so good i.e. I see the button appear in each row. What I needed to do next was to set an image for the UIButton e.g. if the timer was running I wanted to show stop_button_image in the UIButton and if the timer had started I wanted to set the UIImage on the button to start_button_image
The problem is that if the table gets refreshed then I get a nasty traceback depending upon where I had put the UIButton setimage code. Here is my code for reference.
//WORKING CODE: (NOT THAT I WANT)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//TESTING - Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
// Try to retrieve from the table view a now-unused cell with the given identifier.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// If no cell is available, create a new one using the given identifier.
if (cell == nil)
{
// Use the default cell style.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//TESTING - Button
[button addTarget:self
action:#selector(timerStopStart:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Start/Stop" forState:UIControlStateNormal];
button.frame = CGRectMake(5.0f, 5.0f, 72.0f, 77.0f);
button.tag = indexPath.row;
[cell addSubview:button];
//THIS WORKS IF I PUT THIS HERE
[button setImage:[UIImage imageNamed:#"button_pause.png"] forState:UIControlStateNormal];
}
else
{
//NSLog(#"went here 2");
button = (UIButton *) [cell viewWithTag:indexPath.row];
}
//some other logic
}
//CODE BREAKS HERE
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//TESTING - Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
// Try to retrieve from the table view a now-unused cell with the given identifier.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// If no cell is available, create a new one using the given identifier.
if (cell == nil)
{
// Use the default cell style.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//TESTING - Button
[button addTarget:self
action:#selector(timerStopStart:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Start/Stop" forState:UIControlStateNormal];
button.frame = CGRectMake(5.0f, 5.0f, 72.0f, 77.0f);
button.tag = indexPath.row;
[cell addSubview:button];
}
else
{
//NSLog(#"went here 2");
button = (UIButton *) [cell viewWithTag:indexPath.row];
}
//CODE BREAKS HERE
[button setImage:[UIImage imageNamed:#"button_pause.png"] forState:UIControlStateNormal];
//some other logic
}
The problem is that when the table gets refreshed it calls the section with code button = (UIButton *) [cell viewWithTag:indexPath.row]; which I know is just a reference.
Here is the error I get in iOS simulator. I really want to put that image code outside the cell==null check. Any clues how this can be done?
Here is the error that I get in the simulator
2012-06-14 12:39:27.246 Timers[5381:10a03] -[UITableViewCell setImage:forState:]: unrecognized selector sent to instance 0x73706e0
2012-06-14 12:39:27.247 Timers[5381:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell setImage:forState:]: unrecognized selector sent to instance 0x73706e0'
*** First throw call stack:
(0x150b052 0x16bbd0a 0x150cced 0x1471f00 0x1471ce2 0x136c6 0x7b5e0f 0x7b6589 0x7a1dfd 0x7b0851 0x75b322
The problem is probably when the indexPath.row is zero. In that case, you call viewWithTag:0 but as the tag of any UIView is 0 by default, there are chances that a lot of your cell's subview have a tag with the value 0, not only your UIButton.
To avoid this issue, try adding a constant (like 100) to your indexPath.row before affecting it to the tag, so that your button at row 0 will have the tag 100 and not 0 (and button at row 1 will have the tag 101, and so on…), avoiding it to be confused with any other subview with tag 0.
Yeah, this will fail for row 0.
button = (UIButton *) [cell viewWithTag:indexPath.row];
will return cell when indexPath.row is 0, because cell.tag is 0.
As a general note, this approach will not work. The first time you reuse a cell the button will have the wrong tag. For example, if you reuse the cell from row 2 in row 18, then the tag on the button will be 2, but the tag you look for is 18. It will return nil.
why not define a constant #define kMyStopStartButtonTag 12345 and use that constant the whole time.
if (cell == nil)
{
…
button.tag = kMyStopStartButtonTag;
[cell addSubview:button];
…
} else {
button = (UIButton *) [cell viewWithTag:kMyStopStartButtonTag];
}
I have had couple of encounters of this and what I am trying to do is basically calling tableView reloadData however not all the values in the cell is getting updated.The top 5 rows is always not updated... I'd have to scroll to the bottom and then up again to get it updated. Why is this happening?
Here's 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] autorelease];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial" size:16]];
}
//add a button to set to accessory view
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
//I missed setting the frame yesterday!
//[button setFrame:CGRectMake(200, 20, 20, 20)];
[button setImage:[UIImage imageNamed:#"addsource.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(changeButton:) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundColor:[UIColor clearColor]];
cell.accessoryView = button;
if ([[self.content objectAtIndex:indexPath.row] isKindOfClass:[Source class]]){
Source * source = [self.content objectAtIndex:indexPath.row];
if (![source.type isEqualToString:#"featured"]){
[cell.textLabel setText:source.domain];
NSURL* URL = [NSURL URLWithString:source.imageUrl];
[cell.imageView setImageWithURL:URL
placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
}
}
return cell;
}
and this is called everytime I refresh the whole data set:
[self.content removeAllObjects];
[self.content addObjectsFromArray:objects];
[self.tableView reloadData];
try debugging the following line:
if (![source.type isEqualToString:#"featured"]){
obviously your cell won't get updated in the case where your source type is "featured". double check all values in your content array
I've not dug into your code, but this sounds like a symptom you might see when cells are being reused without being fully reset from their previous appearance.
When a cell gets dequeued, it doesn't get reset, it just gets removed from the table view. So unless you do reset it when it next happens to be allocated, it carry previous config and settings.
So, when you configure a cell, make sure you restore all aspects of the cell in all cases, not just those settings for a particular variant of the cell you happen to be returning this time.
Hope that helps.
I'm having a problem with button on uitableview. As in the code, when i click on the button of each cell the image Checked.png should be shown on the button. THis is working fine. However, when i scroll the tableview, the checked image on top of the table disappear.How do i solve this. Can any kind person please help me on this?
//table.m//
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//- (UITableViewCell *)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[[NSBundle mainBundle] loadNibNamed:#"TableCell" owner:self options:NULL];
cell = nibLoadedCell;
button *toggleControl = [[CheckBox alloc] initWithFrame: CGRectMake(270.0, 10.0, 60.0, 60.0)];
toggleControl.tag = toggleControlTag;
[cell.contentView addSubview: toggleControl];
[toggleControl addTarget:self action:#selector(Selected:) forControlEvents:UIControlEventTouchDown];
}
//button.m//
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[self setImage:[UIImage imageNamed:#"Uncheck.png"] forState:UIControlStateNormal];
[self addTarget:self action:#selector(checkBoxClicked) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(IBAction) checkBoxClicked{
if(self.isChecked ==NO){
self.isChecked =YES;
[self setImage:[UIImage imageNamed:#"Checked.png"] forState:UIControlStateNormal];
}else{
self.isChecked =NO;
[self setImage:[UIImage imageNamed:#"Uncheck.png"] forState:UIControlStateNormal];
}
}
You are storing the state for the button in the button. That is the wrong approach. The button is only the view for the state. You need to store your data elsewhere, e.g. in an array, and pull the relevant data for a table cell from the array depending on the indexPath for that cell.
When someone presses your button, you can, e.g., set a BOOL in your data model to indicate that this particular option was selected by the user.
Your cells will always scroll off the view, which will lead to the cells being reused, and your button will no longer be "valid". So you need to check, for every cell that you create, what data you have in your model for this particular part of your data, and fill in the view (= the cell) accordingly.
It wouldn't harm to read up on design patterns.