Hi guys i have a custom tableview cell with a scrollview in it.the problem is all the data is getting loaded in tableview cells at once.what i want is to load the data only for the visible cells in tableView.i used [indexPath forvisiblerows]; it was in vain..cud u guys help me out below is the code.
-(IPadTableViewCell *)getNewCell
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"IpadTableViewCell" owner:nil options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[IPadTableViewCell class]])
{
cell= (IPadTableViewCell *)currentObject;
return cell;
}
}
return nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// static NSString *CellIdentifier = #"IpadTableViewCell";
//cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
id1=[NSString stringWithFormat:#"%i",indexPath.row];
cell=[dicAlbumCells objectForKey:id1];
if (cell == nil) {
cell=[self getNewCell];
}
cell.tag=indexPath.row;
return cell;
}
-(void)loadImagesForOnscreenRows
{
NSArray *visiblePaths = [tblGallery indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths) {
if (imageArray > 0) {
[self imageButtonClicked:nil];
}
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
[self loadImagesForOnscreenRows];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImagesForOnscreenRows];
}
-(void)imageButtonClicked:(id)sender
{
CGFloat prevButtonXPosition = 18, pageButtonXPosition, pageButtonWidth = 144, pageButtonHeight = 143;
for (NSInteger i =0; i<9; i++) {
pageButtonXPosition = prevButtonXPosition ;
prevButtonXPosition = pageButtonXPosition+pageButtonWidth+20;
UIButton *pageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[pageButton setContentMode:UIViewContentModeScaleAspectFit];
pageButton.layer.borderColor=[[UIColor whiteColor]CGColor];
pageButton.layer.borderWidth = 3;
pageButton.layer.cornerRadius = 0;
[pageButton addTarget:self action:#selector(onClickImage:) forControlEvents:UIControlEventTouchUpInside];
[pageButton setFrame:CGRectMake(pageButtonXPosition,0, pageButtonWidth, pageButtonHeight)];
[pageButton setBackgroundImage:[UIImage imageNamed:[imageArray objectAtIndex:i]] forState:UIControlStateNormal];
[pageButton setTag:i];
[cell.scrollView addSubview:pageButton];
}
UIButton *add=[UIButton buttonWithType:UIButtonTypeCustom];
add.layer.borderColor=[[UIColor whiteColor]CGColor];
add.layer.borderWidth = 3;
add.layer.cornerRadius = 0;
[add addTarget:self action:#selector(onClickAdd:) forControlEvents:UIControlEventTouchUpInside];
[add setFrame:CGRectMake(prevButtonXPosition, 0, 144, 143)];
[add setBackgroundImage:[UIImage imageNamed:#"grey.png"] forState:UIControlStateNormal];
[add setTag:0];
[cell.scrollView addSubview:add];
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(prevButtonXPosition+35,30, 76,76)];
[iv setImage:[UIImage imageNamed:#"last.png"]];
[cell.scrollView addSubview:iv];
[cell.scrollView setContentSize:CGSizeMake(prevButtonXPosition +165, 40)];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell.contentView addSubview:cell.scrollView];
}
Related
I have the following implementation where I have title, and two buttons(titles are half and full) on the tablecell. When user selects and close the section and open it again, he only sees the default values of button title which is full rather than his selection.
I could able to see the following method (setHalfButton :indexPath
) is getting called during the reloading, but it does not have any effect.
Code and screenshots are follows.
- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath setQuantity :(double) quantity {
NSMutableArray* array = [selectedRowsInSectionDictionary objectForKey:#(indexPath.section)];
if(array){
[array addObject:indexPath];
} else {
array = [NSMutableArray array];
[array addObject:indexPath];
[selectedRowsInSectionDictionary setObject:array forKey:#(indexPath.section)];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ComboCell";
ComboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[ComboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if([selectedRowsInSectionDictionary[#(indexPath.section)] containsObject: indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if(
comboItemsArray[indexPath.section].allComboItems[indexPath.row].pQuantity == 0.5)
{
// it comes here after reloading
[self setHalfButton:indexPath];
}
else
{
[self setFullButton:indexPath];
}
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.halfBtnOutlet.hidden = YES;
cell.fullBtnOutlet.hidden = YES;
}
cell.comboTitle.text =comboItemsArray[indexPath.section].allComboItems[indexPath.row].pName;
[cell.halfBtnOutlet addTarget:self action:#selector(halfBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.fullBtnOutlet addTarget:self action:#selector(fullBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(void) setHalfButton : (NSIndexPath*)indexPath
{
ComboTableViewCell* cell = [comboTableView cellForRowAtIndexPath:indexPath];
[cell.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[cell.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[cell.halfBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[cell.fullBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
-(void) setFullButton : (NSIndexPath*)indexPath
{
ComboTableViewCell* cell = [comboTableView cellForRowAtIndexPath:indexPath];
[cell.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[cell.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[cell.fullBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[cell.halfBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
Your setHalfButton and setFullButton functions are being called from the cellForRowAtIndexPath: datasource method, but they are calling the cellForRowAtIndexPath: tableview method. Since you have not yet returned the cell from the former method, the latter method will return nil to cell, resulting in no visible update.
The setHalfButton and setFullButton methods should be in your ComboTableViewCell class:
-(void) setHalfButton
{
[self.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[self.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[self.halfBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[self.fullBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
-(void) setFullButton
{
[self.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[self.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[self.fullBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[self.halfBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
Also, you are adding the button action handlers each time you dequeue a cell, but you should only do this when you allocate a new cell. From a design point-of-view these button tap handlers should also be in your ComboTableViewCell class with a delegation pattern to notify the view controller that the half/full was changed.
At the very least it should look something like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ComboCell";
ComboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[ComboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[cell.halfBtnOutlet addTarget:self action:#selector(halfBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.fullBtnOutlet addTarget:self action:#selector(fullBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
}
if([selectedRowsInSectionDictionary[#(indexPath.section)] containsObject: indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if(
comboItemsArray[indexPath.section].allComboItems[indexPath.row].pQuantity == 0.5)
{
// it comes here after reloading
[cell setHalfButton];
}
else
{
[cell setFullButton];
}
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.halfBtnOutlet.hidden = YES;
cell.fullBtnOutlet.hidden = YES;
}
cell.comboTitle.text =comboItemsArray[indexPath.section].allComboItems[indexPath.row].pName;
return cell;
}
The UIButton is created under #implementation . I have to remove it after some functions but[button removeFromSuperview] doesn't work. How can I remove that?
#import "TabBar.h"
#import "CustomCell.h"
#interface TabBar ()
#end
#implementation TabBar
UILabel *title;
NSString *par;
UIButton *button;
NSMutableArray *backlist;
- (NSString *)documentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) lastObject];
}
-(void)tbl_info{
NSString *path = [[self documentsDirectory] stringByAppendingPathComponent:#"icd10.plist"];
self.dataList = [[NSMutableArray alloc] initWithContentsOfFile:path];
for (NSInteger i=[self.dataList count]-1; i>=0;i--) {
NSDictionary *d = [self.dataList objectAtIndex:i];
par=[d objectForKey:#"PARENTID"];
if(![par isEqualToString:self.val])
[self.dataList removeObjectAtIndex:i];
}
}
- (IBAction)ara:(id)sender{
[self tbl_info];
[self.tViewTab reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [self.dataList count];
}
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *name= [[self.dataList objectAtIndex:indexPath.row] objectForKey:#"NAME"];
CGSize maxSize = CGSizeMake(320/2, MAXFLOAT);
CGSize labelSize = [name sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
if(labelSize.height>=63)
labelSize.height=63;
return labelSize.height+1;
}
- (UITableViewCell*)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellid";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
cell = (CustomCell*)[[[NSBundle mainBundle]
loadNibNamed:#"CustomCell" owner:nil options:nil]
lastObject];
}
NSDictionary *d = [self.dataList objectAtIndex:indexPath.row];
cell.nameLabel.text = [d objectForKey:#"NAME"];
cell.cityLabel.text = [d objectForKey:#"CODE"];
cell.indexPath = indexPath;
CGSize maxSize = CGSizeMake(320/2, MAXFLOAT);
CGSize nameSize = [cell.nameLabel.text sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
if(nameSize.height>=63)
nameSize.height=63;
cell.nameLabel.frame =CGRectMake(80, 0, 234, nameSize.height);
cell.cityLabel.text = [d objectForKey:#"CODE"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *d = [self.dataList objectAtIndex:indexPath.row];
NSMutableDictionary *backprop = [[NSMutableDictionary alloc] init];
[backprop setObject:self.val forKey:#"id"];
[backprop setObject:title.text forKey:#"name"];
[backlist addObject:backprop];
//back button
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(touchEvent:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:title.text forState:UIControlStateNormal];
button.frame = CGRectMake(02.0, 02.0, 71, 32);
[self.view addSubview:button];
//parent and title label
[title setText:[d objectForKey:#"NAME"]];
self.val=[d objectForKey:#"ID"];
[self tbl_info];
[self.tViewTab reloadData];
}
-(void)touchEvent:(id)sender{
[title setText:[[backlist objectAtIndex:backlist.count-1] objectForKey:#"name" ]];
self.val= [[backlist objectAtIndex:backlist.count-1] objectForKey:#"id"];
[backlist removeObjectAtIndex:backlist.count-1];
if(backlist.count>0)
[button setTitle:[[backlist objectAtIndex:backlist.count-1] objectForKey:#"name" ] forState:UIControlStateNormal];
else
[button removeFromSuperview];
[self tbl_info];
[self.tViewTab reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
backlist =[[NSMutableArray alloc]init];
self.val=#"0";
[self tbl_info];
[self.tViewTab reloadData];
title =[[UILabel alloc]initWithFrame:CGRectMake(79.0, 07.0, 162, 21)];
title.text = #"ICD10 Kod Grupları"; //etc...
[self.view addSubview:title];
[title release];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
In place of this :
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(touchEvent:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:title.text forState:UIControlStateNormal];
button.frame = CGRectMake(02.0, 02.0, 71, 32);
[self.view addSubview:button];
Try this :
if (button != nil) {
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(touchEvent:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:title.text forState:UIControlStateNormal];
button.frame = CGRectMake(02.0, 02.0, 71, 32);
[self.view addSubview:button];
}
Or try this :
if (button != nil) {
[button removeFromSuperView];
[button release]; // dont write this in case of ARC
button = nil;
}
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(touchEvent:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:title.text forState:UIControlStateNormal];
button.frame = CGRectMake(02.0, 02.0, 71, 32);
[self.view addSubview:button];
Not a solution but a workaround:
Use
[sender removeFromSuperview];
or respectively, because sender is of type id and not UIView*:
[(UIButton*)sender removeFromSuperview];
But you could change sender to UIView* savely.
-(void)touchEvent:(UIView *)sender{
Some even put UIButton* in there. I personally don't like that but it is quite save if you know for sure that the message is sent by UIButtons only.
Another workaround would be to set the .tag property of the button and then fetch the real buttom from self.view by its tag.
I have been racking my brain on this problem for a day or so now... I've searched this forum as well as google and other blogs etc. All to no avail.
What i'm doing is creating a UITableView with multiple sections and within each section, each row has a different GUI element (i.e. a settings screen)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
and all I'm looking to achieve is that each section to have various GUI elements in various cells. BUT as you can see in this screenshot:
Initially everything appears as it should, but after scrolling UP and DOWN once, the problems begin. Elements begin to shuffle around and the more/longer you scroll UP and DOWN the more the elements move around.
!["UITableView with GUI elements in sections and rows. Bug? Glitch? Ignorance?"][2]
Is this a bug? glitch? or ignorance? (probably the latter) - I've stripped out all other code except for the GUI code and if it means anything I'm creating the UITableView using a NIB
Also, here's the code for my cellForRowAtIndexPath method. I will be eternally grateful if someone could point me in the right direction or tell me what i'm doing wrong.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell
// desired section
if(indexPath.section == 0) {
//
// Load Settings
//
// button
UIButton * loadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
loadButton.frame = CGRectMake(0.0, 0.0, 300.0, 44.0);
[loadButton setTitle:#"Load Image" forState:UIControlStateNormal];
[loadButton setTitle:#"Load Image" forState:UIControlStateSelected];
[loadButton addTarget:self action:#selector(loadImage:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:loadButton];
} else if(indexPath.section == 1) {
//
// Mode Settings
//
if(indexPath.row == 0) {
cell.text = [mode objectAtIndex:indexPath.row];
} else if(indexPath.row == 1) {
cell.text = [mode objectAtIndex:indexPath.row];
}
} else if(indexPath.section == 2) {
//
// Marker Settings
//
if(indexPath.row == 0) {
// description text
cell.text = [marker objectAtIndex:indexPath.row];
// switch
UISwitch *markerSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = markerSwitch;
[markerSwitch setOn:YES animated:NO];
[markerSwitch addTarget:self action:#selector(markerToggle:) forControlEvents:UIControlEventValueChanged];
[markerSwitch release];
} else if(indexPath.row == 1) {
UISlider *markerGridSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
cell.accessoryView = markerGridSlider;
markerGridSlider.minimumValueImage = [UIImage imageNamed:#"size_icon_1x1.png"];
markerGridSlider.maximumValueImage = [UIImage imageNamed:#"size_icon_8x8.png"];
[markerGridSlider setMinimumValue:1.0];
[markerGridSlider setMaximumValue:8.0];
markerGridSlider.value = 8.0;
[markerGridSlider addTarget:self action:#selector(markerGrid:) forControlEvents:UIControlEventValueChanged];
[markerGridSlider release];
} else if(indexPath.row == 2) {
UISlider *markerSpacingSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
cell.accessoryView = markerSpacingSlider;
markerSpacingSlider.minimumValueImage = [UIImage imageNamed:#"spacing_icon_min.png"];
markerSpacingSlider.maximumValueImage = [UIImage imageNamed:#"spacing_icon_max.png"];
[markerSpacingSlider setMinimumValue:1.0];
[markerSpacingSlider setMaximumValue:(320.0/8.0)];
markerSpacingSlider.value = 1.0;
[markerSpacingSlider addTarget:self action:#selector(markerSpacing:) forControlEvents:UIControlEventValueChanged];
[markerSpacingSlider release];
}
}
return cell;
}
thanks.
Ken
thanks alon for the help.
maybe i'm not understanding exactly what you mean, but i think i've implemented your suggestions properply. however i still get the glitch of the elements swapping places although now after about 5+ UP and DOWN swipes and my UISwitch is now placed in the top left corner.
here's my updated 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];
if([indexPath section] == 0) {
//
// Load Settings
//
// button
UIButton *loadButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] autorelease];
loadButton.frame = CGRectMake(0.0, 0.0, 300.0, 44.0);
[loadButton addTarget:self action:#selector(loadImage:) forControlEvents:UIControlEventTouchUpInside];
[loadButton setTag:1000];
[cell.contentView addSubview:loadButton];
}
if([indexPath section] == 1) {
//
// Mode Settings
//
if([indexPath row] == 0) {
cell.text = [mode objectAtIndex:[indexPath row]];
}
if([indexPath row] == 1) {
cell.text = [mode objectAtIndex:[indexPath row]];
}
}
if([indexPath section] == 2) {
//
// Marker Settings
//
if([indexPath row] == 0) {
// switch
UISwitch *markerSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[markerSwitch setOn:YES animated:NO];
[markerSwitch addTarget:self action:#selector(markerToggle:) forControlEvents:UIControlEventValueChanged];
[markerSwitch setTag:3000];
[cell.contentView addSubview:markerSwitch];
[markerSwitch release];
}
if([indexPath row] == 1) {
// slider
UISlider *markerGridSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerGridSlider.minimumValueImage = [UIImage imageNamed:#"size_icon_1x1.png"];
markerGridSlider.maximumValueImage = [UIImage imageNamed:#"size_icon_8x8.png"];
[markerGridSlider setMinimumValue:1.0];
[markerGridSlider setMaximumValue:8.0];
[markerGridSlider setValue:8.0];
[markerGridSlider addTarget:self action:#selector(markerGrid:) forControlEvents:UIControlEventValueChanged];
[markerGridSlider setTag:3100];
[cell.contentView addSubview:markerGridSlider];
[markerGridSlider release];
}
if([indexPath row] == 2) {
// slider
UISlider *markerSpacingSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerSpacingSlider.minimumValueImage = [UIImage imageNamed:#"spacing_icon_min.png"];
markerSpacingSlider.maximumValueImage = [UIImage imageNamed:#"spacing_icon_max.png"];
[markerSpacingSlider setMinimumValue:1.0];
[markerSpacingSlider setMaximumValue:(320.0/8.0)];
[markerSpacingSlider setValue:1.0];
[markerSpacingSlider addTarget:self action:#selector(markerSpacing:) forControlEvents:UIControlEventValueChanged];
[markerSpacingSlider setTag:3200];
[cell.contentView addSubview:markerSpacingSlider];
[markerSpacingSlider release];
}
}
} // end cell == nil
// Load
UIButton *loadButton = (UIButton*)[cell.contentView viewWithTag:1000];
[loadButton setTitle:#"Load Image" forState:UIControlStateNormal];
[loadButton setTitle:#"Load Image" forState:UIControlStateSelected];
// Mode
// Marker
UISwitch *markerSwitch = (UISwitch*)[cell.contentView viewWithTag:3000];
UISlider *markerGridSlider = (UISlider*)[cell.contentView viewWithTag:3100];
UISlider *markerSpacingSlider = (UISlider*)[cell.contentView viewWithTag:3200];
return cell;
}
All the cells bound to a UITable in iOS are reusable.
this is why you first get your cell with the function call "dequeueReusableCellWithIdentifier", the cell might not be nil, pointing to a cell that was loaded before. in your case, even if the cell is not nil, you add subviews to it. this will happen infinite times as you scroll up and down.
Here is a small example:
-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* CellIdentifier = #"Cell";
const NSInteger lblTag = 101;
const NSInteger btnTag = 102;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//First init the cells
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//Initialize subviews of cells only in this block.
if (indexPath.row == 0) {
//Only the first cell on the top has a UILabel
UILabel *lbl = [[[UILabel alloc] initWithFrame:CGRectMake(5, 5, 100, 20)] autorelease];
lbl.tag = lblTag;
[cell.contentView addSubview:lbl];
} else if (indexPath.row == 1) {
//Only the 2nd cell has a UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(5, 5, 60, 20);
btn.tag = btnTag;
[cell.contentView addSubview:btn];
}
}
//Modify your cells here
if (indexPath.row == 0) {
//Only the first cell on the top has a UILabel
UILabel *lbl = (UILabel*)[cell.contentView viewWithTag:lblTag];
//Do stuff with our label
lbl.text = [NSString stringWithFormat:#"%d",indexPath.row];
} else if (indexPath.row == 1) {
//Only the 2nd cell has a UIButton
UIButton *btn = (UIButton*)[cell.contentView viewWithTag:btnTag];
//Do stuff with our button
[btn setTitle:[NSString stringWithFormat:#"%d",indexPath.row] forState:UIControlStateNormal];
}
return cell;
}
In your very specific case, you would write this-
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return 1;
} else if (section == 1) {
return 2;
} else if (section == 2) {
return 3;
} else {
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
const NSInteger
sec0BtnTag = 101,
markerSwitchTag = 102,
markerGridSliderTag = 103,
markerSpacingSliderTag = 104;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if([indexPath section] == 0) {
//
// Load Settings
//
// button
UIButton *loadButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] autorelease];
loadButton.frame = CGRectMake(0.0, 0.0, 300.0, 44.0);
[loadButton addTarget:self action:#selector(loadImage:) forControlEvents:UIControlEventTouchUpInside];
[loadButton setTag:sec0BtnTag];
[cell.contentView addSubview:loadButton];
}
else if([indexPath section] == 2) {
//
// Marker Settings
//
if([indexPath row] == 0) {
// switch
UISwitch *markerSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[markerSwitch setOn:YES animated:NO];
[markerSwitch addTarget:self action:#selector(markerToggle:) forControlEvents:UIControlEventValueChanged];
[markerSwitch setTag:markerSwitchTag];
[cell.contentView addSubview:markerSwitch];
[markerSwitch release];
}
else if([indexPath row] == 1) {
// slider
UISlider *markerGridSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerGridSlider.minimumValueImage = [UIImage imageNamed:#"size_icon_1x1.png"];
markerGridSlider.maximumValueImage = [UIImage imageNamed:#"size_icon_8x8.png"];
[markerGridSlider setMinimumValue:1.0];
[markerGridSlider setMaximumValue:8.0];
[markerGridSlider setValue:8.0];
[markerGridSlider addTarget:self action:#selector(markerGrid:) forControlEvents:UIControlEventValueChanged];
[markerGridSlider setTag:markerGridSliderTag];
[cell.contentView addSubview:markerGridSlider];
[markerGridSlider release];
}
else if([indexPath row] == 2) {
// slider
UISlider *markerSpacingSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerSpacingSlider.minimumValueImage = [UIImage imageNamed:#"spacing_icon_min.png"];
markerSpacingSlider.maximumValueImage = [UIImage imageNamed:#"spacing_icon_max.png"];
[markerSpacingSlider setMinimumValue:1.0];
[markerSpacingSlider setMaximumValue:(320.0/8.0)];
[markerSpacingSlider setValue:1.0];
[markerSpacingSlider addTarget:self action:#selector(markerSpacing:) forControlEvents:UIControlEventValueChanged];
[markerSpacingSlider setTag:markerSpacingSliderTag];
[cell.contentView addSubview:markerSpacingSlider];
[markerSpacingSlider release];
}
}
} // end cell == nil
//Load specific cell row values
if([indexPath section] == 0) {
//
// Load Settings
//
// button
UIButton *loadButton = (UIButton*)[cell.contentView viewWithTag:sec0BtnTag];
[loadButton setTitle:#"Load Image" forState:UIControlStateNormal];
[loadButton setTitle:#"Load Image" forState:UIControlStateSelected];
//do other stuff with the button here according to the specific row & section
}
if([indexPath section] == 1) {
//
// Mode Settings
//
if([indexPath row] == 0) {
cell.text = [mode objectAtIndex:[indexPath row]];
}
if([indexPath row] == 1) {
cell.text = [mode objectAtIndex:[indexPath row]];
}
}
if([indexPath section] == 2) {
//
// Marker Settings
//
if([indexPath row] == 0) {
// switch
UISwitch *markerSwitch = (UISwitch*)[cell.contentView viewWithTag:markerSwitchTag];
//do stuff with the switch here according to the specific row & section
}
if([indexPath row] == 1) {
// slider
UISlider *markerGridSlider = (UISlider*)[cell.contentView viewWithTag:markerGridSliderTag];
//do stuff with the slider here according to the specific row & section
}
if([indexPath row] == 2) {
// slider
UISlider *markerSpacingSlider = (UISlider*)[cell.contentView viewWithTag:markerSpacingSliderTag];
//do stuff with the slider here according to the specific row & section
}
}
return cell;
}
change static NSString *CellIdentifier = #"Cell"; for each section like:
NSString *CellIdentifier;
if(indexPath.section==0){ CellIdentifier= #"Cell"; }elseif(indexPath.section==2){ CellIdentifier=#"Cell2"; }
I have two buttons inside sectioned tableview cell thumbs up and thumbs down. Initially image of both button is not selected. When I select thumbs up button its image become thumbs up selected and other one become thumbsdown not selected and vice versa.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"mod:numberOfSectionsInTableView");
NSLog(#"[preferences count]=%d",[preferences count]);
return [preferences count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.choices count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexpath
{
NSLog(#"cellForRowAtIndexPath: DISPLAY TEST");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
NSLog(#"Text is: %#", [choices objectAtIndex:indexpath.row]);
NSLog(#"CHOICE AT INDEX PATH IS: %#",[choices objectAtIndex:indexpath.row %[choices count]]);
cell.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor blackColor];
// Thumbs up button.
//UIButton *thumbsUp = [[UIButton alloc]init];
thumbsUp = [UIButton buttonWithType:UIButtonTypeCustom];
[thumbsUp setTag:(indexpath.row+(indexpath.section * 50))];
[thumbsUp addTarget:self action:#selector(thumbUp_ButtonClicked:event:)
forControlEvents:UIControlEventTouchUpInside];
[thumbsUp setTitle:#"" forState:UIControlStateNormal];
thumbsUp.frame = CGRectMake(150.0, 20, 20, 15);
[thumbsUp setBackgroundImage:[UIImage imageNamed:#"thumbsup_not_selected.png"]
forState:UIControlStateNormal];
//NSLog(#"------------------>TAG TEST : %d",(indexpath.row+(indexpath.section * 50)));
[cell.contentView addSubview:thumbsUp];
// Thumbs down button
thumbsDown = [UIButton buttonWithType:UIButtonTypeCustom];
[thumbsDown addTarget:self action:#selector(thumbDown_ButtonClicked:event:)
forControlEvents:UIControlEventTouchUpInside];
[thumbsDown setTitle:#"" forState:UIControlStateNormal];
thumbsDown.frame = CGRectMake(200, 20, 20, 15);
[thumbsDown setTag:indexpath.row+120];
[cell.contentView addSubview:thumbsDown];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[thumbsDown setBackgroundImage:[UIImage imageNamed:#"thumbsdown_not_selected.png"]
forState:UIControlStateNormal];
}
NSLog(#"------------> TAG TEST %d",thumbsUp.tag);
cell.text = [choices objectAtIndex:(indexpath.row % [choices count])];
NSLog(#"HELLO FOR TESTING");
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
if (sectionTitle == nil) {
return nil;
}
// Create label with section title
UILabel *label = [[[UILabel alloc] init] autorelease];
label.frame = CGRectMake(15, 10, 300, 25);
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor blackColor];
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake(0.0, 1.0);
label.font = [UIFont boldSystemFontOfSize:16];
label.textAlignment = UITextAlignmentLeft;
label.text = sectionTitle;
// Create header view and add label as a subview
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(12, 0, 300, 60)];
[view autorelease];
[view addSubview:label];
//[view addSubview:segmentedControl];
view.backgroundColor = [UIColor grayColor];
return view;
}
//Thumbs Up Button Action
- (IBAction)thumbUp_ButtonClicked:(id)sender event:(id)event
{
NSLog(#"Thumbs Up Check!");
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *) [[button superview] superview];
NSIndexPath *indexPath = [myTable indexPathForCell:cell];
NSLog(#"indexpath =%d",indexPath.row);
//[button setTag:indexPath.row+(indexPath.section * 50)];
int cTag = [sender tag];
NSLog(#"------>TAG : %d", cTag);
NSLog(#"------> Calculated TAG %d",indexPath.row+(indexPath.section * 50));
if(cTag == (indexPath.row+(indexPath.section * 50)))
{
NSLog(#"BUTTON COUNT:");
[button setBackgroundImage:[UIImage imageNamed:#"thumbsup_selected.png"]
forState:UIControlStateNormal];
}
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
//int row = button.tag;
NSLog(#"SECTION IS:%d",section);
NSLog(#"ROW IS: %d",row);
NSArray *array = cell.contentView.subviews;
NSLog(#"NUMBER OF OBJECTS: %d",[array count]);
UIButton *test = (UIButton *)[array objectAtIndex:2];
[test setBackgroundImage:[UIImage imageNamed:#"thumbsdown_not_selected.png"]forState:UIControlStateNormal];
}
Due to issue with tag of button while I change image of one button several buttons are changing. If any one can please find a solution it will be helpful.... tag is setting for buttons in sections which we can view.
The reason is the bad use of the recycling/reuse mechanism (as with 75% of questions about UITableView…)
Go read the Table View Programming Guide in Apple's doc (and search SO and the web for any question related to tableview and the reuse mechanism)
Corrected the issue by creating buttons outside and inside if(cell == nil). Also created a mutable dictionary to keep the current state of the button.....
I want to know how to add the toggling feature to a UIButton, something like the user taps a unselected button the button becomes selected and stays selected till the user taps it again there by making unselected like it was before.
I was thinking of making an IBAction which changes it from unselected to selected, how can I do that?
Heres what I tried:
-(IBAction)toggle {
//Toggle on implementation.
button.selected = YES;
button.highlighted = NO;
button.enabled = YES;
//Toggle off implementation.
if (button.highlighted == YES) {
button.selected = NO;
button.highlighted = YES;
button.enabled = NO;
}
}
Problem...
-(IBAction)toggleFav {
if (favButton == nil) {
UIImage *unselectedImage = [UIImage imageNamed:#"favUntapped.png"];
UIImage *selectedImage = [UIImage imageNamed:#"favTapped.png"];
[favButton setImage:unselectedImage forState:UIControlStateNormal];
[favButton setImage:selectedImage forState:UIControlStateSelected];
[favButton setFrame:CGRectMake(0, 0, 40, 40)];
}
if([favButton isSelected]){
//Add to menu.
[favButton setSelected:NO];
} else {
//Remove from menu.
[favButton setSelected:YES];
}
}
- (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];
UIImage *unselectedImage = [UIImage imageNamed:#"unselected.png"];
UIImage *selectedImage = [UIImage imageNamed:#"selected.png"];
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setBackgroundImage:unselectedImage forState:UIControlStateNormal];
[b setBackgroundImage:selectedImage forState:UIControlStateSelected];
[b addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[b setFrame:CGRectMake(0, 0, 40, 40)];
[cell.contentView addSubview:b];
}
return cell;
}
-(void) buttonPressed:(UIButton *)sender
{
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Your toggleFav code doesn't make much sense.
if (favButton == nil) { checks, if favButton is present. But if you are wiring it up with IB, it should always been there at that point. And if it wasn't how could the button call this method? So do it like this:
-(void)viewDidLoad
{
//....
UIImage *unselectedImage = [UIImage imageNamed:#"favUntapped.png"];
UIImage *selectedImage = [UIImage imageNamed:#"favTapped.png"];
[favButton setImage:unselectedImage forState:UIControlStateNormal];
[favButton setImage:selectedImage forState:UIControlStateSelected];
[favButton setFrame:CGRectMake(0, 0, 40, 40)];
//....
}
-(IBAction)toggleFav:(UIButton *)sender {
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Here you'll find an example project, with a DetaiView, that holds a Button with the 2 states.
Note: I am saving the information of what button was selected in the NSUserDefaults. You should not do that. Instead you'll want to save it in the model. But as I dont have informations on your model, I am just using NSUserDefaults.
-(void)hitButton:(UIButton*)button
{
buttonOnFlag = !buttonOnFlag;
if( buttonFlag )
[self performSelector:#selector(setHighlight:) withObject:button afterDelay:0];
}
- (void)setHighlight:(UIButton*)button
{
button.highlighted = true;
}
Use button.highlighted property
You should code like this:
-(IBAction)toggle:(id)sender {
//Toggle on implementation.
if (sender.highlighted == NO)
{
sender.selected = YES;
sender.highlighted = NO;
sender.enabled = YES;
}
//Toggle off implementation.
else{
sender.selected = NO;
sender.highlighted = YES;
sender.enabled = NO;
}
}