Customized UITableViewCell - iphone

How can i customize a UITableviewCell, as i want to see a label, date and picture in a single cell.

There are two options (may be more). You could use the native UITableViewCell properties to add content to the cell, or create a custom cell (by that I mean, add your own subviews to the Cell). To get started try the first one, it is simple elegant and the results will be quite good. For example try the following cell creation method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// notice the Style. The UITableViewCell has a few very good styles that make your cells look very good with little effort
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
// In my case I get the data from the elements array that has a bunch on dictionaries
NSDictionary *d = [elements objectAtIndex:indexPath.row];
// the textLabel is the main label
cell.textLabel.text = [d objectForKey:#"title"];
// the detailTextLabel is the subtitle
cell.detailTextLabel.text = [d objectForKey:#"date"];
// Set the image on the cell. In this case I load an image from the bundle
cell.imageView.image = [UIImage imageNamed:#"fsaint.png"];
return cell;
}

You can customize UITableViewCell using either Interface Builder or through Code

Have a look at this link.
There you'll find how to make a custom cell with Interface Builder and use it in XCode for your application.
http://www.e-string.com/content/custom-uitableviewcells-interface-builder

I'm a big fan of overriding the UITableViewCell class, and doing custom drawing in self.contentView. This technique is a little more complicated, but it leads to much better scrolling performance.
For example, lets say you override your cell, and have 3 properties on it like so:
#property(nonatomic, retain) UIImage *userPic;
#property(nonatomic, retain) NSString *label;
#property(nonatomic, retain) NSString *date;
Then you can draw them in the cell using the (drawRect:) function:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
[userPic drawInRect: CGRectMake(10, 5, 50, 50)];
[label drawAtPoint:CGPointMake(70, 5) withFont:[UIFont boldSystemFontOfSize:17]];
[date drawAtPoint:CGPointMake(70, 30) withFont:[UIFont systemFontOfSize:14]];
}
For more examples try checking out this framework that uses this style: https://github.com/andrewzimmer906/XCell

Related

Adding a third label to a cell?

As title says I would like to have 3 labels in my cell (in tableView). As can be seen in the code below I currently only have 2 labels which are name, as textLabel and book as detailTextLabel. But what if I also would like chapter as a label (own row in the tabelView cell)? What would be the best way to implement this?
The output should look like this in the tableView:
Name
Book
Chapter
/Thanks in regards!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BookmarkCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Bookmark *item = [self.items objectAtIndex:indexPath.row];
NSArray *chunks = [item.name componentsSeparatedByString: #","];
NSString *name;
NSString *book;
NSString *chapter;
if ([chunks count] > 0)
{
name = [chunks objectAtIndex:0];
if ([chunks count] > 1)
{
book = [chunks objectAtIndex:1];
if ([chunks count] > 2)
{
chapter = [chunks objectAtIndex:2];
}
}
}
cell.textLabel.text = name;
cell.detailTextLabel.text = book;
Sounds like your going to want a custom UITableViewCell and with that you can add anything you would like into it. From there just name the labels that you put into it and write the code accordingly to fill them with the cellForRowAtIndexPath method.
Create a custom UIView and add it as a subview to the cell's contentView. In this custom view add as many UILalels as you would like. You don't actually have to create a custom view to do this, but it allows for greater versatility.
Here is some basic code to achieve three labels.
UIView * pNewContentView= [[UIView alloc] initWithFrame:cell.contentView.bounds];
CGRect labelFrame= pNewContentView.bounds;
labelFrame.size.width= labelFrame.size.width * 0.33;
UILabel* pLabel1=[[UILabel alloc] initWithFrame:labelFrame];
[pNewContentView addSubview:pLabel1];
labelFrame.origin.x= labelFrame.size.width;
UILabel* pLabel2=[[UILabel alloc] initWithFrame:labelFrame];
[pNewContentView addSubview:pLabel2];
labelFrame.origin.x= labelFrame.origin.x + labelFrame.size.width;
UILabel* pLabel3=[[UILabel alloc] initWithFrame:labelFrame];
[pNewContentView addSubview:pLabel3];
[cell.contentView addSubview:pNewContentView];
If what you need is simply another label, then you can do what mark says, create a subview and set it to your cell.
If you want to have something can do more, what you need is a custom UITableViewCell. You can define buttons and other controls. Take a look at this document apple provide. This document can really help to understand how UITableViewCell works so it's worth reading.

Most optimum way to add views in a Custom UITableViewCell

I have seen a lot of examples and I cannot find the best answer.
Imagine that I have a custom cell with a 120 height, with 3 UILabels and a UIImageView.
I init my cell with
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
Of all the approaches, which one its the most optimum?
Probably the best answer for creating custom tables is at the link below, if you then have specific questions about the code you see there, then feel free to ask more questions.
http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
All you have to do is something like this:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Prototype Cell"];
UILabel *label;
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"Prototype Cell"];
label = [[UILabel alloc] init];
label.tag = LABEL_TAG; //Suppose LABEL_TAG is defined someplace else
[cell.contentView addSubview: label];
}
else
{
label = [cell.contentView viewWithTag:LABEL_TAG];
}
label.text = #"Hello World";
//Suppose you want the label at x coordinate 50
label.frame = CGRectMake(0,0,50,120);
//Follow similar steps for all of your subviews
return cell;
}
Create a custom UITableviewCell by subclassing the UITableViewCell & overide the method initWithStyle.You can alloc the labels in this init method & also add this label in the cell in this method.
You can also create the UItableViewCell by using nib files.
http://ijoshsmith.com/2011/07/16/creating-a-custom-uitableviewcell-in-ios-4/

Custom UITableViewCell does not show the labels in storyboard

In this screen shot you can see that I have added UITableView in UIViewController then customized the UITableViewCell by adding some labels in it. But the issue is when I run the application. All of the cells are empty. There are no labels at all.
I am not getting what can be the issue. I have searched the web and read tutorials but couldn't resolve it.
I resolved this issue by myself, just after little effort.
Actually when you create a custom cell you have to do these things:
Setup the labels, images etc on storyboard cell.
Create a custom cell class (inheriting from UITableViewCell)(CustomCell.h & .m), CustomCell.h having all of the properties as iboutlet for labels, images etc. and synthesize them all in implementation.
After creating this custom class go back to storyboard, select the custom cell, change its class to the CustomCell and give it some identifier like "MyCustomCell", then right click on the custom cell and connect the IBOutlets with labels etc.
Now import CustomCell class in the class where you are implementing the UITableView and use the properties you defined in CustomCell class.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyCustomCell";
CustomCell*cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the provided setImageWithURL: method to load the web image
// Ensure you use a placeholder image otherwise cells will be initialized with no image
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://example.com/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder"]];
cell.myCustomLabel.text = #"My Text";
return cell;
}
I did this all and my issue was resolved and please don't forget to connect the delegates & datasource and table.
Hope this will help others.
It is little bit late but you can solve your problem by setting the background color of your view as Clear Color from your storyboard.
in the tableview's delegate method , cellforrowatindexpath has a uitableviewcell inside it , there should be an identifier in the initialization of this cell. possibly it is "cell" or "cellIdentifier" .
you just need to select your cell from storyboard and enter this identifier string to the storyboard , where uitableviewcell's attribute inspector stays.
hope this helps.. :)
First Set cell identifier in storyboard #"Cell"
then set tag of label
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}
UILabel *lblDate = (UILabel*)[cell viewWithTag:101];
UILabel *lblDistance = (UILabel*)[cell viewWithTag:102];
UILabel *lbltype = (UILabel*)[cell viewWithTag:103];
lblDate.text = [temp objectAtIndex:indexPath.row] valueForKey:#"date"] stringByReplacingOccurrencesOfString:#"-" withString:#"/"]];
lblDistance.text = [NSString stringWithFormat:#"%# KM",[[temp objectAtIndex:indexPath.row] valueForKey:#"distance"]];
NSString *type = [NSString stringWithFormat:#"%#",[[temp objectAtIndex:indexPath.row] valueForKey:#"distance"]];
if([type isEqualToString:#"0"])
{
lbltype.text = #"Personal";
}
else
{
lbltype.text = #"Bussiness";
}
// Configure
return cell;
}

Slow scrolling in UITableView containing UI Elements in each cell

I have 3 segmented controls in each cell of a tableview on an iPad. The orientation is always landscape for the app and the number of cells vary for each run on the app. The app performs fine if the number of rows are around less than 10, but anywhere above that, the glitches start to appear.
For the kind of application I'm building, I could have as many as 70 rows ==> meaning, 210 UISegmentedControls, all alloced in the memory at once.
Is there a work around? Is there a way I can reuse these UISegmentedControls? If yes, how can I preserve the state of the segmented control?
Otherwise, can anybody propose a new solution? (Each segmented control has items 'A' and 'B' and there are three segmented controls representing three different parameters for each object corresponding to each row of the table).
UPDATE:
Here's the 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];
}
// Configure the cell...
segmentedControl1 = (UISegmentedControl*)[array1 objectAtIndex:[indexPath row]];
segmentedControl1.frame = CGRectMake(180, 15, 100, 30);
[cell.contentView addSubview:segmentedControl1];
segmentedControl2 = (UISegmentedControl*)[array2 objectAtIndex:[indexPath row]];
segmentedControl2.frame = CGRectMake(450, 15, 100, 30);
[cell.contentView addSubview:segmentedControl2];
segmentedControl3 = (UISegmentedControl*)[array3 objectAtIndex:[indexPath row]];
segmentedControl3.frame = CGRectMake(725, 15, 100, 30);
[cell.contentView addSubview:segmentedControl3];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Create a custom UITableViewCell subclass. Have three properties in it for your three UISegmentedControls and add them in the init method:
#interfate MyCell : UITableViewCell
#property (nonatomic, retain, readonly) UISegmentedControl *control1;
#property (nonatomic, retain, readonly) UISegmentedControl *control2;
#property (nonatomic, retain, readonly) UISegmentedControl *control3;
#end
#implementation
#synthesize control1 = _control1;
#synthesize control2 = _control2;
#synthesize control3 = _control2;
- (id)init
{
if ((self = [super init]))
{
_control1 = [[UISegmentedControl alloc] init...];
_control1.frame = CGRectMake(...);
[self addSubView:_control1];
// repeat with control2 & control3
}
//...
#end
Then, rather than storing arrays of UISegmentedControls you can then have arrays of NSNumber holding the selected index.
You'd then do something like:
cell.control1.selectedIndex = [[array1 objectAtIndex:indexPath.row] integerValue];
You could also create custom objects to hold this data and store them in one array.
You should be re-using UITableViewCells, which contain three generic UISegmentedControls. When tableView:cellForRowAtIndexPath: is called, you should set the correct values for each segmented control - always.
Those values have to be stored "somewhere else", outside cells, most likely in same place as where you get the other data for cells.
Update with draft code, should not compile as-is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"CellId";
static NSString *cellNib = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellNib owner:self options:nil];
for (id nibItem in nib)
{
if ([nibItem isKindOfClass:[UITableViewCell class]])
{
cell = (UITableViewCell *)nibItem;
break;
}
}
}
// Configure the cell, all values!
UISegmentedControl *seg = nil;
seg = (UISegmentedControl *)[cell viewWithTag:1];
seg.selectedSegmentIndex = 0
UISegmentedControl *seg = nil;
seg = (UISegmentedControl *)[cell viewWithTag:2];
seg.selectedSegmentIndex = 0
return cell;
}
The idea is that you create a custom UITableViewCell template in Interface Builder with 3 segmented Controls. Give each control a UNIQUE tag id number. Use the tag id to get access to each specific control and setup ALL VALUES - because you are reusing the same cells and by default they will contain old values.
Btw about cell non-selection... Well, there are many ways to do that, wrote even a blog about it "How to Disable UITableCell Selection". Yep, it's old and got title wrong, but should work.
Hope this helps :)
I've never seen a UITableView keep "live" more than one or two cells beyond those visible on the screen. Are you using dequeueReusableCellWithIdentifier to recycle your cells?
I suspect that your problem is something other than segmented controls. A UITableView has built-in methods to take care of loading and reloading classes as they go off-screen, so all 210 controls should not be in memory at once.
I would start by checking to make sure that you are using dequeueReusableCellWithIdentifier: correctly (especially if each UITableViewCell is the same class). Maybe also check for memory leaks.
You can allocate the segmented controls in your cell for row at index path when the cells are being created.
Allocate them in cell for row at index path. Allocate and add the segmented controls under the (cell == nil) condition.
Or
You can reuse 3 segmented controls for all the cells. And hold an array for keeping the changed values.

problem in display in a tableView

as you see in the screen prints, tableView always displays a single value in the tableView "Title" My problem is to display all the array values ​​detailTableView
- (void)viewDidLoad {
NSArray* tmpArray = [[NSArray alloc] initWithObjects:#"Titre", #"Nom", #"Prenon",#"Adresse",#"Phone",#"Mobile",#"Mail",#"Site",#"Note",nil];
self.detailsTableView = tmpArray;
[tmpArray release];
[super viewDidLoad];
}
- (UITableViewCell *)tableView:(UITableView *)atableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
cell.textLabel.text =[self.detailsTableView objectAtIndex:indexPath.row] ;
return cell;
}
From the screen grab, it looks like you've only got one cell per section. In which case you need to use indexPath.section instead of indexPath.row.
From the apple Documentation
textLabel
Returns the label used for the main textual content of the table cell. (read-only)
#property(nonatomic, readonly, retain) UILabel *textLabel
Discussion
Holds the main label of the cell. UITableViewCell adds an appropriate label when you create the cell in a given cell style. See “Cell Styles” for descriptions of the main label in currently defined cell styles.
So Create a new UILabel and add it to textLabel
did you set as follows:
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
return [self.detailsTableView count];
}