I followed Apple's documentation on adding subview to the UITableViewcell here
to add a 3rd label to the cell. The problem is when I show the standard checkmark accessory view on the right the whole cell contents moves left even when I didn't show the 3rd label.
Screenshot below .
And here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyCell";
UILabel *mainLabel, *secondLabel, *thirdLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
cell.accessoryType = UITableViewCellAccessoryNone;
mainLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 2.0, 100.0, 21.0)];
mainLabel.tag = MAINLABEL_TAG;
//mainLabel.font = [UIFont systemFontOfSize:14.0];
//mainLabel.font = [UIFont fontWithName:#"Geeza Pro Bold" size:17.0];
mainLabel.font = [UIFont boldSystemFontOfSize:17];
mainLabel.textAlignment = UITextAlignmentLeft;
mainLabel.textColor = [UIColor blackColor];
mainLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:mainLabel];
secondLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 22.0, 100.0, 21.0)];
secondLabel.tag = SECONDLABEL_TAG;
//secondLabel.font = [UIFont systemFontOfSize:12.0];
//secondLabel.font = [UIFont fontWithName:#"Geeza Pro" size:15.0];
secondLabel.font = [UIFont systemFontOfSize:15];
secondLabel.textAlignment = UITextAlignmentLeft;
secondLabel.textColor = [UIColor darkGrayColor];
secondLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:secondLabel];
thirdLabel = [[UILabel alloc] initWithFrame:CGRectMake(203.0, 11.0, 70.0, 21.0)];
thirdLabel.tag = THIRDLABEL_TAG;
//thirdLabel.font = [UIFont systemFontOfSize:12.0];
//thirdLabel.font = [UIFont fontWithName:#"Geeza Pro Bold" size:17.0];
thirdLabel.font = [UIFont boldSystemFontOfSize:17];
thirdLabel.textAlignment = UITextAlignmentRight;
thirdLabel.textColor = [UIColor darkGrayColor];
thirdLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:thirdLabel];
}
else
{
mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
secondLabel = (UILabel *)[cell.contentView viewWithTag:SECONDLABEL_TAG];
thirdLabel = (UILabel *)[cell.contentView viewWithTag:THIRDLABEL_TAG];
}
Car *car = [self.dataModel carAtIndex:indexPath.row];
NSString *carName = [NSString stringWithFormat:#"%#",car.deviceName];
NSString *carDetails = [NSString stringWithFormat:#"%# at %#",car.date,car.location];
NSString *carSpeed = [NSString stringWithFormat:#"%# km/h",car.speed];
mainLabel.text = carName;
secondLabel.text = carDetails;
thirdLabel.text = carSpeed;
return cell;
}
UPDATE: I changed UIViewAutoresizingFlexibleLeftMargin to UIViewAutoresizingFlexibleWidth according to #MattG advice. Now when a cell is selected the Labels don't move to the left but are a little partially covered as in the pic below.
Maybe this caused by my - (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath ? Here is its code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark){
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
else
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
}
I would start by reviewing Apple's Table View Programming Guide for iOS. It has a section called 'A Closer Look at Table View Cells' which breaks down the layouts of the pre-defined cells.
Looking at your code You have enough going on in your cells to consider subclassing UITableViewCell to produce your own custom cell. You could remove all of your setup code for your cell labels into one class and just concern yourself with configuring the cell in the cellForRowAtIndexPath: method.
However your question is focused on layout of the table view cell. It is sometimes useful to set the subviews' backgrounds to different colors so you can see what space is being used by which subview and how it interacts if we introduce other subviews, in this case the accessory view.
To fix your issue with the third label's text being truncated would be to first to configure the label to work with a smaller font size. I would do this for all the labels. The labels should now adjust the text based on the label's width. You should also check you text alignment property to confirm they are set to the best option.
thirdLabel.adjustsFontSizeToFitWidth = YES;
thirdLabel.minimumScaleFactor = 0.4f;
The results of these changes might be enough to solve the truncation and keep a layout that you have.
Adjust the constraints of your cells so that nothing is being constrained by that side the accessory type shows up on.
For example, I had my accessory show up on the right side, however my cell items were constrained to all 4 edges (top, bottom, left, right). Since the accessory was a right checkmark, i changed my items to top, left, height & width constraints, (skipping the right) and now, when the accessory shows up, it doesn't shift the right anchor point.
Related
I am using table view using custom coding with tag method to save memory.
I was successful to show data in the view but the problem is if 10 cells are showing and then if I scroll down like for one cell then it should show 2-11 cell data but it switches to 1-10 again.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *cellNAMElabl = nil;
UILabel *cellDetaillabl = nil;
UIImageView *imgView = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
cellNAMElabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 10, 150, 20)];
[cellNAMElabl setTag:1];
cellNAMElabl.text = [name5 objectAtIndex:indexPath.row];
UIFont *myFont1 = [ UIFont fontWithName: #"Arial" size: 20.0 ];
cellNAMElabl.font = myFont1;
[cell.contentView addSubview:cellNAMElabl];
cellDetaillabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 28, 150, 20)];
[cellDetaillabl setTag:2];
cellDetaillabl.text = [email5 objectAtIndex:indexPath.row];
UIFont *myFont = [ UIFont fontWithName: #"Arial" size: 13.0 ];
cellDetaillabl.font = myFont;
[cell.contentView addSubview:cellDetaillabl];
imgView=[[UIImageView alloc] initWithFrame:CGRectMake(25, 5, 52, 50)];
[imgView setTag:3];
imgView.image = [imagepath5 objectAtIndex:indexPath.row];
[cell.contentView addSubview:imgView];
}
cellNAMElabl = (UILabel *)[cell viewWithTag:1];
cellDetaillabl = (UILabel*)[cell viewWithTag:2];
imgView = (UIImageView*)[cell viewWithTag:3];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
You are not assigning new content to subviews, if they have been already created. After the case if(cell == nil), these you have just got references.
cellNAMElabl = (UILabel *)[cell viewWithTag:1];
cellDetaillabl = (UILabel*)[cell viewWithTag:2];
imgView = (UIImageView*)[cell viewWithTag:3];
Here when cell is not nil, you are just getting references to labels and imageview, but you are not setting new text and image from data source. Add following lines and remove them from the if (cell == nil) part:
cellNAMElabl.text = [name5 objectAtIndex:indexPath.row];
cellDetaillabl.text = [email5 objectAtIndex:indexPath.row];
imgView.image = [imagepath5 objectAtIndex:indexPath.row];
[cell.contentView addSubview:imgView];
The way this dequeueReusableCellWithIdentifier works: If iOS detects that a cell is not displayed anymore, then dequeueReusableCellWithIdentifier will return that cell. If there is no unused cell, it returns nil. So what you need to do:
If dequeueReusableCellWithIdentifier returns nil, then you create a new cell, and you do all the setup that is required for all cells with the same identifier. For example, add view tags like you did, set fonts, colors etc.
Then, whether you use a cell returned by dequeueReusableCellWithIdentifier or one that you just created yourself, you add all the information that is used for the specific section/row that you want to display. So if row 1, row2, and so on display different text, then you set the text here. That's what you didn't do, so when a cell was reused, you didn't set the new text for it.
So the idea is that all the work that is the same for all rows is only done once when a cell is created, and only as many cells are created as is needed to display them on the screen. The work that is different from row to row is done for each row, as it is needed.
If you set a breakpoint in the if cell == nil block its probably only being hit for the first set if your reuseID is correct. Thats why its never getting a chance to set any new data into the cell.
You should not look for a nil cell, rather use a correct reuseID and a prototype cell in IB that is set to a custom UITableViewCell subclass you create.
Its also good practice to implement prepareForReuse on custom cells, where you clear any cell data e.g. label.text = nil, imageview.image = nil
This way you dont get invalid data from previously dequeued cells. It might not solve the question directly, but it would have wiped the fixed data set in your if cell == nil block to help debug.
What you want to do is..
add/setup the tableViewCell UI if the cell is nil..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
UILabel *cellNAMElabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 10, 150, 20)];
cellNAMElabl.tag = 1;
cellNAMElabl.font = [UIFont fontWithName: #"Arial" size: 20.0 ];
[cell.contentView addSubview:cellNAMElabl];
UILabel *cellDetaillabl = [[UILabel alloc] initWithFrame:CGRectMake(88, 28, 150, 20)];
cellDetaillabl.tag = 2;
cellDetaillabl.font = [UIFont fontWithName: #"Arial" size: 13.0 ];
[cell.contentView addSubview:cellDetaillabl];
UIImageView *imgView=[[UIImageView alloc] initWithFrame:CGRectMake(25, 5, 52, 50)];
imgView.tag = 3;
[cell.contentView addSubview:imgView];
}
//and just update your data if the cell is currently exist and not nil..
//you already called the view using tag so, you dont need those:
// UILabel *cellNAMElabl = nil;
// UILabel *cellDetaillabl = nil;
// UIImageView *imgView = nil;
((UILabel *)[cell viewWithTag:1]).text = [name5 objectAtIndex:indexPath.row]; // cellNAMElabl
((UILabel*)[cell viewWithTag:2]).text = [email5 objectAtIndex:indexPath.row]; // cellDetaillabl
((UIImageView*)[cell viewWithTag:3]).image = [imagepath5 objectAtIndex:indexPath.row]; // imgView
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
hope this have help you, happy coding cheers!
I want to implement data sheet to display history of user. I want to implement that design like this:
But I dont know how to do that...Can anyone please help me
Edit:
Add the horizontal line at the specific position and the label at the position and it will look like this.
Create a tableview and than in cellForRowAtIndexPath method add this code..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *SimpleTableIdentifier;
UITableViewCell * cell;
SimpleTableIdentifier = #"SimpleTableIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier: nil];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
UILabel * numLbl = [[UILabel alloc] initWithFrame:CGRectMake(0,5,33,30)];
numLbl.text = #"1";
[numLbl setFont:[UIFont fontWithName:#"Helvetica" size:10.0]];
numLbl.backgroundColor = [UIColor clearColor];
[cell addSubview:numLbl];
UILabel * nameLbl = [[UILabel alloc] initWithFrame:CGRectMake(30,5,50,30)];
nameLbl.text = #"john%Lakeview";
[nameLbl setFont:[UIFont fontWithName:#"Helvetica" size:10.0]];
nameLbl.backgroundColor = [UIColor clearColor];
[cell addSubview:nameLbl];
//create a hoizontal separator in cell to display it like column
UIView* hSeparatorview1 = [[UIView alloc] initWithFrame:CGRectMake(25, 0, 1, 30)];
hSeparatorview1.backgroundColor = [UIColor blackColor];
hSeparatorview1.tag = 1;
[cell addSubview:hSeparatorview1];
UIView* hSeparatorview2 = [[UIView alloc] initWithFrame:CGRectMake(85, 0, 1, 30)];
hSeparatorview2.backgroundColor = [UIColor blackColor];
hSeparatorview2.tag = 2;
[cell addSubview:hSeparatorview2];
}
return cell;
}
//this method is used to set the hight of the tableview cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
return 30;
}
I have created it for only two label and two horizontal view but you can create as many as you like.
And yes dot forget to place this code in didSelectRowAtIndexPath otherwise horizontal view will disappear when user click the cell.
- (void)tableView:(UITableView *)atableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//get the cell which is selected
UITableViewCell *selectedCell = [atableView cellForRowAtIndexPath:indexPath];
//set cell horizontal saparator view color of selected cell bcoz when cell selected all view color is gone
UIView *hSeparatorview1=[selectedCell viewWithTag:1];
hSeparatorview1.backgroundColor = [UIColor blackColor];
UIView *hSeparatorview2=[selectedCell viewWithTag:2];
hSeparatorview2.backgroundColor = [UIColor blackColor];
}
Better to try with Custom tableview Cell for text,and UIViews for lines.I'm also done the same in my app.
I made custom cell with scrollViewon right side of the cell and imageView on left side. Now when I click on imageView I get correct value for indexPath.row, but when I click on scrollView indexPath.row is returning value from last image that was clicked. Any suggestions how to fix this?
EDIT:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *hlCellID = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:hlCellID];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:hlCellID];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
UIScrollView *scrollView = (UIScrollView *)[cell viewWithTag:16];
scrollView.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0];
scrollView.delegate = self;
scrollView.scrollEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width,scrollView.frame.size.height);
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
int i=0;
for(i=0;i<15;i++){
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0+i*100, 0, 100, 100)];
label.text = #"HELLO";
label.textColor = [UIColor blackColor];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont fontWithName:#"ArialMT" size:18];
[scrollView addSubview:label];
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width+i*label.frame.size.width,scrolView.frame.size.height);
}
return cell;
}
UIScrollView *scrollView = (UIScrollView *)[cell viewWithTag:16];
Change above line with following.
UIScrollView *scrollView = (UIScrollView *)[cell viewWithTag:indexPath.row];
i hope this works for you..
You should look at this doc reference: responder chain
Basically your event doesn't goes uphill the responder chain because scroll view captures it. I don't know what you are trying to achieve but having scrollview inside a scrollview(because tables are scrollviews by their nature) is bad idea and is really hard to achieve.
Im adding 2 texts into a cell of a table. What I am doing is
UITableViewCell *cell =nil;
NSString *CellIdentifier = #"Cell";
cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
[[UILabel alloc] initWithFrame:CGRectMake(80.0, 0.0, 220.0, 10.0)];
mainLabel.tag = 1003;
mainLabel.text = #"Text 1";
mainLabel.textAlignment = UITextAlignmentLeft;
mainLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|
UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:mainLabel];
}
I do the same thing to add secondLabel to a cell.
What is displaying on the simulator is
Now the problem is the background of 2 UILabel is not the same with the background of the cell ( my cells are grouped in the table view )
Does anyone know how to fix this problem.
Any comments are welcomed here
Thanks
If I have understand well the question, you need to delete the UILabel background because you want to show the UITableViewCell background instead. So I think you only have to do that:
mainLabel.backgroundColor = [UIColor clearColor];
Like the answer above, you should set the same color for both of the view.
cell.backgroundColor = [UIColor clearColor];
or you can set the color of the View you set.
I'm really new to Xcode and Objective C but I can't seem to find a tutorial on a simple table I'd like to create. I'd like to have a table (grouped style) with only three rows but two columns. Column A would have a label (like 'Name:') and column B would have the actual data ("Jason").
I can't seem to find how to do this. Unless I'm just completely looking up the wrong thing? Was hoping someone could help me on how to do this or point me in the right direction.
Thank you!!
You don't want to use a table with 2 columns. They are not used in iOS.
You should use a UITableViewCell with a UITableViewCellStyleValue2 style. And you want to set #"Name" as textLabel.text and #"Jason" as detailTextLabel.text.
You have to change the tableView:cellForRowAtIndexPath: a little bit.
// 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:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"Name";
cell.detailTextLabel.text = #"Jason";
return cell;
}
You can't "really" create columns in UITableView, but you can use Cell Styles to achieve a similar effect.
You can use the UITableViewCellStyleValue1 style to achieve what you say
Here is an exemple:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = #"Name";
cell.detailTextLabel.text = #"Jason";
return cell;
}
Here is an exemple of what it looks like:
http://blog.blackwhale.at/wp-content/uploads/2009/06/Bild-3.png
Or, but more complicated if you are new to ObjectiveC, you can create your own CellView in a XIB and use it in your code:
http://www.bdunagan.com/2009/06/28/custom-uitableviewcell-from-a-xib-in-interface-builder/
Edit: Sorry, fluchtpunkt has been faster than me ;)
maybe you should add a label on the table cell, and give a border
like this :
//------------------- first column -------------------------------------------------------------------
UILabel * label1 = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 312, 43)];
[label1 setFont:[UIFont fontWithName:#"arial" size:18]];
[label1 setTextColor:[UIColor blackColor]];
label1.backgroundColor = [UIColor clearColor];
label1.layer.borderColor=[[UIColor lightGrayColor]CGColor];
label1.layer.borderWidth= 1.0f;
label1.numberOfLines = 0;
label1.text = [NSString stringWithFormat:#" %#",[[yourArray objectAtIndex:indexPath.row]objectForKey:#"xxxxx"]];
[cell.contentView addSubview:label1];
//------------------- second column -------------------------------------------------------------------
UILabel * label2 = [[UILabel alloc]initWithFrame:CGRectMake(314, 0, 125, 43)];
[label2 setFont:[UIFont fontWithName:#"arial" size:18]];
[label2 setTextColor:[UIColor blackColor]];
label2.textAlignment = NSTextAlignmentCenter;
label2.backgroundColor = [UIColor clearColor];
label2.layer.borderColor=[[UIColor lightGrayColor]CGColor];
label2.layer.borderWidth= 1.0f;
label2.text = [NSString stringWithFormat:#"%#",[[yourArray objectAtIndex:indexPath.row]objectForKey:#"xxxxxx"]];
[cell.contentView addSubview:label2];