UITableView scrolling changess image inside UITableViewCell - iphone

I am displaying some data using a UITableViewController, my table has 2 static sections with 6 static rows each. And I am subclassing UITableViewCell in order to add 3 Labels and a View, in the view I draw an arrow in only one of the cells in one of the sections.
This all goes perfectly fine. Till i scroll down... then the arrow is randomly placed in other cells, once i scroll back up the arrow has again changed cells... This also happens if i try to set a backgroundColor for only one of the cells. Once I scroll down and up the cell that originally had the color no longer has it, and another seemingly random cell has the color now.
Here is some of my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
TableViewCells *cell = (TableViewCells *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[TableViewCells alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(TableViewCells *)cell atIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case 0:
{
if (indexPath.section == cotizacionIdeal)
{
cell.arrowImage = [UIImage imageNamed:#"arrowUp.png"];
[cell.nombre setText:#"Recursos"];
[cell.cantidad setText:[NSString stringWithFormat:#"%1.2f", [cotizacionPrevia.sueldoDeRecursos doubleValue]]];
[cell.porcentaje setText:[NSString stringWithFormat:#"%1.2f%#", [cotizacion.recursosPorcentaje doubleValue], #"%"]];
}
else
{
[cell.nombre setText:#"Recursos"];
[cell.cantidad setText:[NSString stringWithFormat:#"%1.2f", [cotizacionPrevia.sueldoDeRecursos doubleValue]]];
[cell.porcentaje setText:[Calculate calcPorcentaje:cotizacionPrevia.sueldoDeRecursos totalReal:self.totalReal]];
}
}
break;
case 1:
{
if (indexPath.section == cotizacionIdeal)
{
[cell.nombre setText:#"Comision de Venta"];
[cell.cantidad setText:[Calculate calcMonto:cotizacion.comisionPorcentaje total:self.totalIdeal]];
[cell.porcentaje setText:[NSString stringWithFormat:#"%1.2f%#", [cotizacion.comisionPorcentaje doubleValue], #"%"]];
}
else
{
[cell.nombre setText:#"Comision de Venta"];
[cell.cantidad setText:self.montoRealComision];
[cell.porcentaje setText:[NSString stringWithFormat:#"%1.2f%#", [cotizacion.comisionPorcentaje doubleValue], #"%"]];
}
}
UITableViewCell class:
- (id)initWithFrame:(CGRect)frame cell:(TableViewCells *)cell
{
if (self = [super initWithFrame:frame]) {
_cell = cell;
//self.opaque = YES;
//self.backgroundColor = _cell.backgroundColor;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
[_cell.arrowImage drawAtPoint:CGPointMake(0, 0)];
}
#end
#implementation TableViewCells
#synthesize nombre;
#synthesize porcentaje;
#synthesize cantidad;
#synthesize arrowImage;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// Initialization code
UILabel *nombreLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.nombre = nombreLabel;
[nombreLabel release];
[self.nombre setFont:[UIFont boldSystemFontOfSize:14]];
[self.contentView addSubview:self.nombre];
UILabel *porcentajeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.porcentaje = porcentajeLabel;
[porcentajeLabel release];
[self.porcentaje setFont:[UIFont italicSystemFontOfSize:10]];
[self.contentView addSubview:self.porcentaje];
UILabel *cantidadLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.cantidad = cantidadLabel;
[self.cantidad setTextAlignment:UITextAlignmentRight];
[cantidadLabel release];
[self.cantidad setFont:[UIFont boldSystemFontOfSize:14]];
[self.contentView addSubview:self.cantidad];
cellContentView = [[TableViewCellContentView alloc] initWithFrame:CGRectZero cell:self];
cellContentView.backgroundColor = [UIColor clearColor];
[self.contentView addSubview:cellContentView];
}
UPDATE:
I have also tried setting the image to a different one for everyone but one and I am still having the same issue.
- (void)configureCell:(TableViewCells *)cell atIndexPath:(NSIndexPath *)indexPath {
cell.arrowImage = [UIImage imageNamed:#"arrowDown.png"];
switch (indexPath.row) {
case 0:
{
if (indexPath.section == cotizacionIdeal)
{
cell.arrowImage = [UIImage imageNamed:#"arrowUp.png"];
[cell.nombre setText:#"Recursos"];
[cell.cantidad setText:[NSString stringWithFormat:#"%1.2f", [cotizacionPrevia.sueldoDeRecursos doubleValue]]];
[cell.porcentaje setText:[NSString stringWithFormat:#"%1.2f%#", [cotizacion.recursosPorcentaje doubleValue], #"%"]];
}
else
{

The problem is that whenever you use drawRect for a cell you MUST call setneedsdisplay. That is what fixed my problem.

The issue is that the UITableView reuses cells so that it doesn't need to make more instances than are displayed and you're not explicitly removing the arrow in your configureCell method.
If the arrow shouldn't be displayed on a cell, explicitly clear it out in the configureCell method and that should fix it.

I am not 100% on this but I think it is to do with the release of the image. When you use imageNamed, the instance is retained so it is suggested to use imageWithFilePath instead.
Hope this helps....

Related

Check image not working properly in uitableviewcell over button, tag and cell reuse issue

Check Images removing after scrolling.
I have to reuse cell and also dont want to use didselectrow method because i am having several buttons in one cell and this is the sample i created for stackoverflow.
I searched a lot in google and found helpless.
Here Is my Sample Code
//
// TVViewController.h
// tableviewcheck
#import <UIKit/UIKit.h>
#interface TVViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
UITableView *sampleTableView;
UIImageView * imageView1;
UIButton* aButton1;
UIImageView *imageViewchk1;
int tag;
}
#property (nonatomic, strong) IBOutlet UITableView *sampleTableView;
#end
// TVViewController.m
// tableviewcheck
#import "TVViewController.h"
#interface TVViewController ()
#end
#implementation TVViewController
#synthesize sampleTableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// Return the number of rows in the section.
// Usually the number of items in your array (the one that holds your list)
// NSLog(#"selected %i and deliveryArray %i",[queueArray count],[deliveryArray count]);
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Where we configure the cell in each row
// NSString *CellIdentifier =[NSString stringWithFormat:#"%i-%i", indexPath.section,indexPath.row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
imageViewchk1 = [[UIImageView alloc] initWithFrame:CGRectMake(56,0 , 24,24)];
imageViewchk1.image = [UIImage imageNamed:#"check.png"];
imageViewchk1.tag=indexPath.row+10000;
imageViewchk1.hidden=YES;
imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80,80)];
imageView1.image = [UIImage imageNamed:#"newframe.png"];
aButton1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton1 setTag:indexPath.row];
[aButton1 setImage:imageView1.image forState:UIControlStateNormal];
aButton1.frame = CGRectMake(0, 0, 80,80);
[aButton1 addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aButton1 addSubview:imageViewchk1];
[cell.contentView addSubview:aButton1];
return cell;
}
-(void)buttonClicked:(UIButton*)sender {
tag = sender.tag;
NSLog(#"buttonClicked %i",tag);
UIImageView *imageView = (UIImageView *)[sampleTableView viewWithTag:tag+10000];
if(imageView.hidden)
{
imageView.hidden=NO;
}
else {
imageView.hidden=YES;
}
}
Well, the problem with you implementation is, that you only set the imageView.hidden property in the buttonClicked method.
When a cell is not shown on the screen for a moment and then shown again, cellForRow is called again.
The problem here is, that you do not store in which cell the imageView.hidden has been set to NO. That is why every time a cell is shown again, the cellForRow: sets its imageView.hidden to YES.
So solution will be to store the numbers of the cell, where imageView.hidden= NO and check in cellForRow if the cell at that indexpath is one where imageView.hidden= NO.
Answering My Own Question For the People searching same Functionality, Here How i did the changes
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
tempArray=[[NSMutableArray alloc] init];
for(int count=0;count<50;count++)
[tempArray addObject:[NSNumber numberWithBool:NO]];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// Return the number of rows in the section.
// Usually the number of items in your array (the one that holds your list)
// NSLog(#"selected %i and deliveryArray %i",[queueArray count],[deliveryArray count]);
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80,80)];
imageView1.image = [UIImage imageNamed:#"newframe.png"];
imageViewchk1 = [[UIImageView alloc] initWithFrame:CGRectMake(56,0 , 24,24)];
imageViewchk1.image = [UIImage imageNamed:#"check.png"];
imageViewchk1.tag=indexPath.row+10000;
imageViewchk1.hidden=YES;
aButton1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton1 setTag:indexPath.row];
[aButton1 setImage:imageView1.image forState:UIControlStateNormal];
aButton1.frame = CGRectMake(0, 0, 80,80);
[aButton1 addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aButton1 addSubview:imageViewchk1];
BOOL selected=[[tempArray objectAtIndex:indexPath.row] boolValue];
if(selected)
{
// imageViewchk1.image = [UIImage imageNamed:#"check.png"];
imageViewchk1.hidden=NO;
}
else
{
imageViewchk1.hidden=YES;
}
[cell.contentView addSubview:aButton1];
return cell;
}
-(void)buttonClicked:(UIButton*)sender {
tag = sender.tag;
NSLog(#"buttonClicked %i",tag);
NSIndexPath *index=[sampleTableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
BOOL selected=[[tempArray objectAtIndex:index.row] boolValue];
if(selected)
{
[tempArray replaceObjectAtIndex:index.row withObject:[NSNumber numberWithBool:NO]];
}
else
[tempArray replaceObjectAtIndex:index.row withObject:[NSNumber numberWithBool:YES]];
[sampleTableView reloadData];
}

can't change UITableViewCell background color

I have UITableViewCell that fits on UITableView, but somehow I can't change the background color when entering editing style mode.. I've tried everything on the web, search all day long, but still couldn't get it fixed (I've searched StackOverflow as-well). please, help me.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MainTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"MainTableViewCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (MainTableViewCell *)view;
}
}
}
Try customizing the cell inside tableView: willDisplayCell: method, something like this:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [UIColor redColor];
}
You need to change the tableView cell's contentView, not the cell's background view.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.contentView.backgroundColor = [UIColor redColor];
}
to have total control on the customisation of your cells, I prefer better to override the cell view,
create a new class for your cell view, that gets called by the UITableView,
later when i get to my work computer if you havent found your answer I will post some sample code,
once you see how it works is pretty easy
you could as well place an image for your cell background, and place different labels and images, buttons, textfields in custom places of your cell,
EDIT>>
the code! [is overkill just to change the background, but if you want to really customise your cell, this is the way to go!]
in your CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell {
UILabel *_kLabel;
UILabel *_dLabel;
}
#property (nonatomic, retain) UILabel *kLabel;
#property (nonatomic, retain) UILabel *dLabel;
- (void) initLabels;
#end
in your CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
#synthesize kLabel = _kLabel;
#synthesize dLabel = _dLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
CGRect popUpImageBgndRect = CGRectMake(0, 0, 942, 44);
UIImageView *popUpImageBgnd = [[UIImageView alloc] initWithFrame:popUpImageBgndRect];
[popUpImageBgnd setImage:[UIImage imageNamed:#"tableCellBgnd.png"]];
popUpImageBgnd.opaque = YES; // explicitly opaque for performance
[self.contentView addSubview:popUpImageBgnd];
[popUpImageBgnd release];
[self initLabels];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+10 ,10, 200, 20);
self.kLabel.frame = frame;
frame= CGRectMake(boundsX+98 ,10, 100, 20);
self.dLabel.frame = frame;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void) initLabels {
self.kLabel = [[[UILabel alloc]init] autorelease];
self.kLabel.textAlignment = UITextAlignmentLeft;
self.kLabel.backgroundColor = [UIColor clearColor];
self.kLabel.font = [UIFont fontWithName:#"FS Albert" size:16];
self.kLabel.textColor = [UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1];
self.dLabel = [[[UILabel alloc]init] autorelease];
self.dLabel.textAlignment = UITextAlignmentLeft;
self.dLabel.backgroundColor = [UIColor clearColor];
self.dLabel.font = [UIFont systemFontOfSize:16];
self.dLabel.textColor = [UIColor colorWithRed:51.0f/255.0f green:51.0f/255.0f blue:51.0f/255.0f alpha:1];
[self.contentView addSubview:self.kLabel];
[self.contentView addSubview:self.dLabel];
}
-(void) dealloc {
[_kLabel release];
[_dLabel release];
[super dealloc];
}
#end
And in your ViewController.m
YourViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
ENJOY!!
;)
try setting the cells backgroundColor property, worked for me cell.backgroundColor=[UIColor blueColor];
Please try this, it works for me.
UIView *bgView = [[UIView alloc] initWithFrame:cell.frame];
bgView.backgroundColor = [UIColor greenColor];
cell.backgroundView = bgView;
[bgView release];
As #Westley mentioned;
You need to change the tableView cell's contentView, not the cell's background view.
This is how you should do it:
if(index == conditionYouWant)
{
cell.contentView.backgroundColor = [UIColor whiteColor];
}
else
{
cell.contentView.backgroundColor = [UIColor colorWithRed:0.925 green:0.933 blue:0.937 alpha:1.0];
}
Hope it helps you guys out
Be sure you didn't already set the content view's background color in the Storyboard. If you did, changing the cell.backgroundColor in code will make no difference, and you will go round and round in confusion (like I did).
cell.backgroundColor = [UIColor redColor];
in swift 3 you can use
cell.backgroundcolor = UIColor.white

How to make UITableView Like Below Image?

How to make UITableView like above image?
I know this is grouped table type. but how we can add the image+label+button to header of section.
I have tried
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
but it starts with CGRectMake(0,0,320,height).
I want just above section and exact width of section just like in image.
Thanks in advance.
Instead of trying to change the section header view, you might want to create a custom cell with a brown background, a label and a button and use it for the first row. So, in -cellForRowAtIndexPath, you could do something like
if (0 == indexPath.row) {
return brownCell;
} else {
return normalCell;
}
There are several ways to create custom cells, I always start from the Table View Programming Guide for iOS.
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell{
id delegate;
NSIndexPath *indexpath;
}
#property(nonatomic,assign) id delegate;
#property(nonatomic,retain)NSIndexPath *indexpath;
#property(nonatomic,retain) IBOutlet UIToolbar *Toolbar;
-(IBAction)SelectorLeft:(id)sender;
-(IBAction)SelectorRight:(id)sender;
#end
customcell.m
#import "CustomCell.h"
#import <QuartzCore/QuartzCore.h>
#implementation CustomCell
#synthesize Toolbar;
#synthesize delegate,indexpath;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
-(IBAction)SelectorLeft:(id)sender{
[delegate perfromselector:#selector(left:) withObject:indexpath];
}
-(IBAction)SelectorRight:(id)sender{
[delegate perfromselector:#selector(left:) withObject:indexpath];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
UItbaleView part
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"identifier";
NSUInteger row = [indexPath row];
if (row == 0) {
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
self.Cell = nil;
[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = self.Cell;
}
cell.Toolbar.clipsToBounds=YES;
CALayer *l=cell.Toolbar.layer;
// set corner radious
[l setCornerRadius:10];
// to apply border on corners
[l setBorderColor:[[UIColor clearColor] CGColor]];
// to apply set border width.
[l setBorderWidth:5.0];
return cell;
}else{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %i",row];
cell.delegate = self;
cell.indexpath = indexpath;
return cell;
}
return nil;
}
Also do n't forget to create Customcell.xib and add tool bar through interface builder
also create an outlet of CustomCell in tableview class and handle it as above
its easy all what you have to
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
if (row % 2 == 0) {
static NSString *identifier = #"RowOne";
UITableViewCell *cell = (RowTypeOne*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault]autorelease];
}
cell.Title.text = [datasource objectatindex:row];
cell.Title.font = [UIFont fontWithName:#"Tahoma" size:16];
cell.contentView.backgroundColor = [UIColor redColor];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.textAlignment = UITextAlignmentRight;
return cell;
}else if (row % 2 == 1) {
static NSString *identifier = #"RowTwo";
UITableViewCell *cell = (RowTypeOne*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault]autorelease];
}
cell.contentView.backgroundColor = [UIColor redColor];
cell.Title.text = [datasource objectatindex:row];
cell.Title.font = [UIFont fontWithName:#"Tahoma" size:16];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.textAlignment = UITextAlignmentRight;
return cell;
}
return nil;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
//create btn left each on handeled by selector
UIBarButtonItem *btnleft = [[UIBarButtonItem alloc] initWithTitle:#"List of sms" style:UIBarButtonItemStylePlain target:self action:#selector(ListClicked:)];
//create btn right each on handeled by selector
UIBarButtonItem *btnright = [[UIBarButtonItem alloc] initWithTitle:#"New" style:UIBarButtonItemStyleBordered target:self action:#selector(NewClicked:)];
//create uitoolbar then add btns to it as list of array
UIToolbar *tool = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
//change style of toolbar to be black
[tool setBarStyle:UIBarStyleBlack];
tool.items = [NSArray arrayWithObjects:btnleft,[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],btnright, nil];
//this is the parent view that we will add on it the uitoolbar objects and the buttons
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
[view autorelease];
[view addSubview:tool];
return view;
}
-(void)ListClicked:(id)sender{
//handle here btn left
}
-(void)NewClicked:(id)sender{
//handle here btn right
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 44;
}
if you want the cell not to be in the header you can check for first row in cellforrow at index path...
also if you want to do it in another style you can make custom cell and add it also to cellforrowatindexpath

Accordion table cell - How to dynamically expand/contract uitableviewcell?

I am trying create an accordion type of uitableviewcell that, when the user selects the cell, it expands to display a detailed info view inline similar to how the digg app works. I initially tried replacing the current tablecell with a customcell in cellForRowAtIndex, however the animation looks a bit choppy as you can see the cell being replaced and overall the effect doesn't work too well.
If you look at the digg app and others who have done this it seems that they aren't replacing the current cell but instead perhaps adding a subview to the cell? The original cell however doesn't seem to animate at all and only the new view accordions into the table.
Does anyone have any ideas how to accomplish a similar effect?
I have made some progress using neha's method below and while the cell is animating the correct way it is wreaking havoc with the other cells in the table. What I have done is subclassed UITableViewCell with a custom class which contains an instance of a UIView which actually draws the view which I then add to the table cell's contentview.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
if (selected) {
[self expandCell];
}
}
-(void)expandCell {
self.contentView.frame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 110);
}
Here are all the table delegate methods I am using:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = #"SearchCell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)];
theText.text = #"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:#"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
selectedIndex = indexPath.row;
isSearching = YES;
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
return 110;
}
return rowHeight;
}
It seems now that the cell is expanding but not actually being refreshed so the labels, and textfield aren't being shown. They do however show up when I scroll the cell off and on the screen.
Any ideas?
The Apple way to do is quite simple.
First, you'll need to save the selected indexPath row:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedRowIndex = [indexPath retain];
[tableView beginUpdates];
[tableView endUpdates];
}
I'll explain the begin/end updated part later.
Then, when you have the currently selected index, you can tell the tableView that it should give that row more space.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//check if the index actually exists
if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {
return 100;
}
return 44;
}
This will return height 100 for the selected cell.
Now we can go back to the begin/end updates. That block triggers the reload of all tableView geometry. Moreover, that block is animated, which eventually gives the impressions of the row expanding.
Pawel's beginUpdates/endUpdates trick is good, and I often use it. But in this case you simply need to reload the rows that are changing state, ensuring that you correctly reload them with the desired cell type, and that you return the correct new cell height.
Here is a complete working implementation of what I think you're trying to accomplish:
.h:
#import <UIKit/UIKit.h>
#interface ExpandingTableViewController : UITableViewController
{
}
#property (retain) NSIndexPath* selectedIndexPath;
#end
.m:
#implementation ExpandingTableViewController
#synthesize selectedIndexPath;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier1 = #"Cell1";
static NSString *CellIdentifier2 = #"Cell2";
UITableViewCell *cell;
NSIndexPath* indexPathSelected = self.selectedIndexPath;
if ( nil == indexPathSelected || [indexPathSelected compare: indexPath] != NSOrderedSame )
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %d", indexPath.row];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier2] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %d", indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat: #"(expanded!)", indexPath.row];
}
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( self.selectedIndexPath != nil && [self.selectedIndexPath compare: indexPath] == NSOrderedSame )
{
return tableView.rowHeight * 2;
}
return tableView.rowHeight;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray* toReload = [NSArray arrayWithObjects: indexPath, self.selectedIndexPath, nil];
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths: toReload withRowAnimation: UITableViewRowAnimationMiddle];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
#end
If you don't want to reload the cell (you want to keep your existing cell and just change the size, and likely add/remove some subviews), then simply do the beginUpdates/endUpdates trick in didSelectRowAtIndexPath:, and call some method on your cell to incite the layout change. beginUpdates/endUpdates will prompt the tableView to re-query the heights for each cell - so be sure to return the correct value.
Create a class that subclasses UITableviewcell in your project. Create this class' nib and set its parent to be the class in your project with tableview and override its -
(void)setSelected:(BOOL)selected animated:(BOOL)animated
Write methods contractCell() and expandCell() in this class, and provide the height of the cells you want in expandCell method. Call this methods appropriately based on some flags set to identify wheather the cell is in expanded state or contracted state. Use your tableview's
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
method to handle selection of cells.
Replace your cellForRowAtIndexPath function with this one.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = #"SearchCell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0,
10.0, cell.contentView.bounds.size.width
-20, 22.0)];
theText.text = #"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 +
46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0,
88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:#"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
}
create array wof dictionary which have a key Select_sts which is 0 in start when click its change 1
accourding u change table
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 40.0)];
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.opaque = NO;
headerLabel.textColor = [UIColor blackColor];
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.frame = CGRectMake(5.0, 10.0, 300.0, 20.0);
headerLabel.text=[NSString stringWithFormat: #"PNR %#",[[record objectAtIndex:section] objectForKey:#"number"]];
customView.backgroundColor=[UIColor whiteColor];
btn_openClose.tag=section+10000;
btn_openClose.backgroundColor=[UIColor clearColor];
// [btn_openClose setImage:[UIImage imageNamed:#"down_arrow.png"] forState:UIControlStateNormal];
[btn_openClose addTarget:self action:#selector(collapseExpandButtonTap:) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:btn_openClose];
}
- (void) collapseExpandButtonTap:(id) sender{
int indexNo=[sender tag]-10000;
// NSLog(#"total_record %#",[total_record objectAtIndex:indexNo]);
NSMutableDictionary *mutDictionary = [[total_record objectAtIndex:indexNo] mutableCopy];
if([[mutDictionary objectForKey:#"Select_sts"] integerValue]==0)
[mutDictionary setObject:[NSNumber numberWithInt:1] forKey:#"√"];
else
[mutDictionary setObject:[NSNumber numberWithInt:0] forKey:#"Select_sts"];
[total_record replaceObjectAtIndex:indexNo withObject:mutDictionary];
// [table_view beginUpdates];
// [table_view reloadData];
// [table_view endUpdates];
NSMutableIndexSet *indetsetToUpdate = [[NSMutableIndexSet alloc]init];
[indetsetToUpdate addIndex:indexNo]; // [indetsetToUpdate addIndex:<#(NSUInteger)#>]
// You can add multiple indexes(sections) here.
[table_view reloadSections:indetsetToUpdate withRowAnimation:UITableViewRowAnimationFade];
}

UITableView reloading data / refreshing (possible duplication issue)

I have a UITableView in an iPhone application which I am refreshing (by calling [self.tableView reloadData] in the action method for a UISegmentedControl dynamically embedded in one of the UITableView cells. The table view is refreshed to update a text value for one of the cells.
However, the following code seems to produce an unwanted side-effect. It appears that each time the UITableView refreshes it creates a new instance of the UISegmentedControl (and possibly the images - I'm not sure) over the existing one(s).
The only reason I notice this is that with each refresh a barely perceptible border starts to form around the UISegmentedControl and the application slows noticeably. I would be extremely grateful for any suggestions/code-solutions to my current predicament.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSUInteger section = indexPath.section;
NSUInteger row = indexPath.row;
// Set up the cell...
//populates the personal info section
if (section == kPersonalInfoAddSection) {
if (row == kNameRow) {
//Other code irrelevant to this question was removed for the sake of clarity
}
else if(row == kHeightRow) {
cell.imageView.image = [UIImage imageNamed:#"tableview_height_label.png"];
//THIS IS THE TEXT I'M TRYING TO UPDATE
cell.textLabel.text = [Formatter formatHeightValue:mainUser.heightInMM forZone:self.heightZone];
cell.detailTextLabel.text = REQUIRED_STRING;
}
}
//populates the units section
if (section == kUnitsSection) {
if (row == kHeightUnitsRow) {
NSArray *heightUnitsSegments = [[NSArray alloc] initWithObjects:FT_AND_IN_STRING, M_AND_CM_STRING, nil];
UISegmentedControl *heightUnitControl = [[UISegmentedControl alloc] initWithItems:heightUnitsSegments];
CGRect segmentRect = CGRectMake(90, 7, 200, 30);
[heightUnitControl setFrame:segmentRect];
//[heightUnitControl setSelectedSegmentIndex:0];
[heightUnitControl addTarget:self action:#selector(heightSegmentClicked:) forControlEvents:UIControlEventValueChanged];
heightUnitControl.tag = kHeightSegmentedControlTag;
cell.textLabel.text = #"Height:";
cell.detailTextLabel.text = #"(units)";
[cell.contentView addSubview:heightUnitControl];
[heightUnitsSegments release];
[heightUnitControl release];
}
else if(row == kWeightUnitsRow) {
//Other code irrelevant to this question was removed for the sake of clarity
}
}
return cell;
}
Thank you all in advance!
You're right, it is creating a new instance of the UISegmentedControl. It's because you are using a generic cell identifier, #"Cell", then adding the UISegmentedControl each time, never removing it. The cells get cached containing the UISegmentedControl, you retrieve the cached cell and add the control again.
You could use a more specific cell identifier and if cell != nil you know it contains the UISegmentedControl already. Or create a new cell each time that way you're not using a cached cell that already contains the control.
With the image view you just set the cells image view property without adding a new view to the cell so that one is ok, it gets replaced each time.
Since the text you are trying to update doesn't have to do with the UISegmentedControl I think you should be able to use a more specific cell identifier and add the control only on cell creation.
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr1=[NSArray arrayWithObjects:#"img1.jpg",#"img2.jpg",nil];
NSArray *arr2=[NSArray arrayWithObjects:#"img1.jpg",#"img2.jpg",#"img3.jpg",#"img4.jpg",#"img5.jpg",#"img6.jpg",nil];
NSArray *arr3=[NSArray arrayWithObjects:#"img6.jpg",#"img5.jpg",#"img2.jpg",#"img1.jpg",nil];
Imgs = [[NSArray alloc] initWithArray:[NSArray arrayWithObjects:arr1,arr2,arr3,nil]];
NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:#"Ahmedabad",#"Name",#"Picture 5.png",#"Rating",#"Picture 1.png",#"Photo",arr1,#"img",nil];
NSDictionary *dic2=[NSDictionary dictionaryWithObjectsAndKeys:#"Rajkot",#"Name",#"Picture 5.png",#"Rating",#"Picture 2.png",#"Photo",nil];
NSDictionary *dic3=[NSDictionary dictionaryWithObjectsAndKeys:#"Baroda",#"Name",#"Picture 5.png",#"Rating",#"Picture 7.png",#"Photo",nil];
tblArray=[[NSArray alloc] initWithObjects:dic1,dic2,dic3,nil];
[myTbl reloadData];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden=NO;
[self.navigationController.navigationBar setUserInteractionEnabled:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.navigationBarHidden=YES;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [tblArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifer=[NSString stringWithFormat:#"%i",indexPath.row];
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifer];
if(cell==nil){
cell=[self myCustomCell:CellIdentifer dicToSet:[tblArray objectAtIndex:indexPath.row]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
return cell;
}
-(UITableViewCell*)myCustomCell:(NSString*)CellIdentifer dicToSet:(NSDictionary*)dicToSet{
UITableViewCell *cell=[[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 44) reuseIdentifier:CellIdentifer] autorelease];
UIImageView *imgV=[[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 40, 40)];
[imgV setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Photo"]]];
[cell addSubview:imgV];
[imgV release];
UILabel *lbl=[[UILabel alloc] initWithFrame:CGRectMake(44, 2, 276, 20)];
[lbl setText:[dicToSet valueForKey:#"Name"]];
[cell addSubview:lbl];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setFont:[UIFont fontWithName:#"Helvetica-Bold" size:18]];
[lbl release];
UIImageView *imgV1=[[UIImageView alloc] initWithFrame:CGRectMake(44, 24, 70, 20)];
[imgV1 setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Rating"]]];
[cell addSubview:imgV1];
[imgV1 release];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
nxtPlcDtl=[[plcFullDtl alloc] initWithNibName:#"plcFullDtl" bundle:nil];
nxtPlcDtl.dict=[[NSDictionary alloc] initWithDictionary:[tblArray objectAtIndex:indexPath.row]];
nxtPlcDtl.Imgs = [Imgs objectAtIndex:indexPath.row];
nxtPlcDtl.comment1 = [comment1 objectAtIndex:indexPath.row];
nxtPlcDtl.vedio = [vedio objectAtIndex:indexPath.row];
[self.navigationController pushViewController:nxtPlcDtl animated:YES];
}