Dividing Cells in a UITableView - ios

I am attempting to obtain this result to get a TitleTextLabel|DescTextLabel with the line to break the two. Just like this example the homepage is divided from the URL field.
Can someone please point me in the right direction? I have read online / & the documentation but cannot find the right answer I'm looking for. I appreciate your help!
Thanks

There are a couple of ways I can think of to add that dividing line. You could override drawRect, and draw the line there. Another way that could be done wholly in IB, would be to add a 1 pixel wide label (with a light gray background an no text) in between the left and right labels. The left label should have a fixed width and constraints to the left side of the cell and to the 1 pixel wide label. The right label should just have constraints to the 1 pixel wide label and the right side of the cell (no fixed width). The 1 pixel wide label should have 0 length constraints to the top and bottom of the cell and a fixed width.

You need to draw that line on the cell manually.
1) Create UIView subclass called CellDividerView Override the -drawRect: method in the UIView subclass CellDividerView.m. The drawing code fills the entire rect with a solid color, dark gray in this case.
- (void)drawRect:(CGRect)rect
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetFillColorWithColor(currentContext, [UIColor lightGrayColor].CGColor);
CGContextFillRect(currentContext, rect);
CGContextRestoreGState(currentContext);
}
In the table view delegate's -tableView:cellForRowAtIndexPath: you create and init a CellDividerView with the frame positioned where you want it on the cell. In the code below it is positioned 40pts to the right, 0pts from the top, and it is 1pt wide and spans the entire cell height vertically. Next, this view is added to the cell's contentView.
#define CELL_VIEW_TAG 1234
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Section %u", indexPath.section];
cell.textLabel.text = [NSString stringWithFormat:#"Row %u", indexPath.row];
// Configure the cell...
CellView *cellView = (CellView *)[cell.contentView viewWithTag:CELL_VIEW_TAG];
if (!cellView)
{
cellView = [[CellView alloc] initWithFrame:CGRectMake(40.0, 0.0, 1.0, cell.contentView.frame.size.height)];
[cell.contentView addSubview:cellView];
cellView.tag = CELL_VIEW_TAG;
}
return cell;
}
The result is something like this:
Using a custom cell style and adjusting the 40.0pt offset will allow you to accurately position the line where you want it.

It doesn't have the line dividing it by default, but try UITableViewCellStyleValue2

Related

Can I set my autolayout constraints so that an imageview is set to the height of the image

I am building out a dynamic tableview cell. The height is dynamic based on the content that is loaded. I'm running into a hangup with height of the imageview. The images currently load aspect fill in an imageview that is 100% of the width. Is it possible to set an autolayout constraint on my imageview so that the imageview is hidden (has a height of 0) if there is no image for a tableview cell?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewTileCell *cell = [tableView dequeueReusableCellWithIdentifier:#"tileCell"];
if (!cell)
{
[tableView registerNib:[UINib nibWithNibName:#"TableViewTileCell" bundle:nil] forCellReuseIdentifier:#"tileCell"];
cell = [tableView dequeueReusableCellWithIdentifier:#"tileCell"];
}
cell.tileView.layer.borderColor = [UIColor blackColor].CGColor;
cell.tileView.layer.borderWidth = 1.0f;
[cell.contentView setBackgroundColor:[UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0]];
NSString *url=[self.resultsArray[indexPath.row] valueForKey:#"imageURL"];
cell.tileTitle.text = [self.resultsArray[indexPath.row] valueForKey:#"title"];
cell.tileDate.text = [self.resultsArray[indexPath.row] valueForKey:#"date"];
cell.tileContent.text = [self.resultsArray[indexPath.row] valueForKey:#"summary"];
if(![url isEqualToString:#""]){ //If we got a url value back load the image
[cell.tileImageview setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
return cell;
}
Is it possible to set an autolayout constraint on my imageview so that the imageview is hidden (has a height of 0) if there is no image for a tableview cell?
Make the whole cell content a vertical UIStackView. In cellForRow, make the image view hidden. The stack view has the wonderful ability to change the constraints in exactly the way you describe: when the image view is hidden, the constraints will change and the image view will occupy zero space, with the other views occupying the whole space.
The alternative is not terrible: you simply have to do, yourself, what the UIStackView would do — remove the empty image view in code and adjust the constraints, in cellForRow. Swapping constraints and views together into and out of the interface is standard practice, and is easy to do.

Displaying image in sliding menu

I have small question. How to display profile picture and UserFullName and State and Country in single label dynamically from a service in sliding menu like below attached image. TIA
Design tablecell like this or you can also design UIView in sidebar like same.
Programmatically set corner radius of image so it's look round.
Yes you can set all in one label expect to imageview
do this
[_demolabel setText:[NSString stringWithFormat:#" UserFullName \n State Country"]];
And apply your suitable logic for label height and width.
Image you can not add in Label, you need a separate outlet for Image.
Displaying in single label is bit tricky. You have to use NSAttributted Text. After reading the name of the user needed to append a \n to truncate the next line data.
label.numberOFLines = 0; (you have to set this for label)
Best option Use two label one for User name and next one is for location give proper auto layout and spacing between them, then you are done.
Use Custom Cell you can get the image,name,state and country
First you need to create Custom UITableView Cell.In xib file you need to set ImageView,name label and staecountry label also connect(drag in .h).
please import the Quartzcore framework for forming circle
#import <QuartzCore/QuartzCore.h>
in TableView DataSource Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return yourArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.imgViewDetail.image = [UIImage imageNamed:#"imagename.png"];
cell.imgView.layer.borderWidth = 2.0;
cell.imgView.layer.cornerRadius = cell.yourImageView.frame.size.height /2;
cell.imgView.layer.masksToBounds = YES;
cell.labelName.text = #"James Stevens";
cell.labelStateCountry.text = [NSString stringWithFormat:#"%#%#",#"Sydney",#"Australia"];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
Important - You have to give imageView width and height as 200,200 or 100,100 or 50,50....whatever you want to give equal width and height when you set imageView as circle
You can't set UserFullName, State and Country in single label. You need to use two labels, set image like your attached pic, and round corners.
For example:
Imageview.layer.cornerRadius=10;
[Imageview.layer setMasksToBounds:YES];

Rearranging Cell Subviews When UITableViewCell Resizes

I have a UITableViewCell that is implemented using storyboard that looks like:
Here is what the cell should look like without an image:
I have been fiddling with the constraints and banging my head trying to figure this out but have had no luck. I have a pretty good understanding of constraints and how to add them programmatically but have had no luck with this specific problem and feel like I am just adding layout constraints to the cell willy-nilly with no logical thought process. The cell represents a newsfeed post which may or may not have an image in the main image view at the top, and should behave as follows. If the cell doesn't have an image in it the bottom bar with the like and comment counts, moves up to align with the top of the cell. I achieved this behaviour by setting a constraint that kept the smaller image view, post title, post time and the post content a set distance away from the bottom of the cell. This approach works and when the cell is resized in the heightForRowAtIndexPath method the subviews move appropriately. The problem comes when the text in the post content is larger then a single line. The height of the cell adjusts correctly but the top of the text view stays at the same location and grows downward and overflows into the next cell. When I place the constraints to align the four subviews with the top of the cell I run into issues when there is no image and the post content is larger then a single line. In this case, the cell resizes to be smaller than its original size and the subviews stay at the distance specified by the constraint. The smaller image, post title, time and content are clipped and don't display. This is such an odd problem with so many different cases. I have been working at this for almost two days and could really use someone else's thoughts on how to solve this issue. I hope this isn't too confusing, thanks for the help!
I have one way to solve this, but I'm sure there are many others. I gave both image views a fixed height constraint. The small image view and the top label (Post Title) have fixed heights to the top of the cell -- both of these as well as the height constraint of the large image view have IBOutlets to them so they can be changed in code. The bottom label (Post Content) has its number of lines set to 0, and has an IBOutlet to its height constraint (all the labels had the standard 21 point height to start). In code, I check for the existence of an image at each indexPath, and change the constraints accordingly.
- (void)viewDidLoad {
UIImage *image1 = [UIImage imageNamed:#"House.tiff"];
[super viewDidLoad];
self.theData = #[#{#"pic":image1, #"post":#"short post"},#{#"post":#"short post"},#{#"pic":image1, #"post":#"Long long post with some extra stuff, and even some more"},#{#"post":#"Long long post with some extra stuff, and even some more"}];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat ivHeight = (self.theData[indexPath.row][#"pic"])? 215 : 0; // 215 is the fixed height of the large image view
CGSize labelSize = [self.theData[indexPath.row][#"post"] sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:CGSizeMake(152, CGFLOAT_MAX)];
return 140 + ivHeight + labelSize.height; // the 140 was determined empirically to get the right spacing between the 3 labels and the bottom bar
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row][#"post"];
cell.iv.image = self.theData[indexPath.row][#"pic"];
if(self.theData[indexPath.row][#"pic"] == nil){
cell.heightCon.constant = 0; // heightCon is the outlet to the large image view's height constraint
cell.ivTopCon.constant = 8; // ivTopCon is the outlet to the small image view's spacing to the top of the cell
cell.labelTopCon.constant = 8; // labelTopCon is the outlet to thetop label's spacing to the top of the cell
}else{
cell.heightCon.constant = 215; // this number and the following 2 are taken from the values in IB
cell.ivTopCon.constant = 185;
cell.labelTopCon.constant = 233;
}
CGSize labelSize = [self.theData[indexPath.row][#"post"] sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:CGSizeMake(152, CGFLOAT_MAX)];
cell.labelHeightCon.constant = labelSize.height;
return cell;
}
Hey #rdelmar thanks for the solution! Eventually I ended up just designing two different cells in the storyboard file with different reuse identifiers but the same subclass. I then checked in the cellForRowAtIndexPath method if the cell had content or not, and assigned the correct identifier. If this is the incorrect way of doing this, or will cause problems down the road please let me no in the comments.

Dynamic Height UILabel works after moving offscreen

I am trying to create multi-line dynamic UILabels in UITableViewCells. I have a custom UITableViewCell that has a 'comment' label. The cell and the label are created in storyboard.
I can compute the heights of the UITableViewCells properly based on the multi-line data to be stored in the UILabel (using heightForRowAtIndexPath). However, my problem lies in the actual UILabel content. The UILabel content will display only 1 line of data on table load. However, once a cell containing multiline UILabel data moves offscreen and comes back on screen, the multi-line data appears properly in the UILabel with multiple lines. Is there any way to fix this so that the multi-line data appears properly on table load?
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cCell = (CustomCell *)cell;
MyObject = [myArray objectAtIndex:indexPath.row];
cCell.commentLabel.frame = CGRectMake(65.0f, 28.0f, 243.0f, 200.0f);
cCell.commentLabel.text = MyObject.multi_line_text_data;
cCell.commentLabel.adjustsFontSizeToFitWidth = NO;
cCell.commentLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
cCell.commentLabel.font = [UIFont systemFontOfSize:13.0];
cCell.commentLabel.lineBreakMode = NSLineBreakByWordWrapping;
cCell.commentLabel.numberOfLines = 0;
[cCell.commentLabel sizeToFit];
}
Thanks!
Since you're doing this in the storyboard, you can set the necessary label properties there (lineBreakMode and number of lines). Just give the label a specific width constraint and constraints to the top, bottom, and left sides of the cell. Then, in code use sizeWithFont:constrainedToSize:lineBreakMode: in heightForRowAtIndexPath: to calculate the appropriate height for the cell based on the content of the label -- the label, because of its constraints, will expand along with the cell to the proper size. Something like this:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGSize rowSize = [self.theData[indexPath.row] sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(260, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
return rowSize.height + 30;
}
Here, 260 was the width I gave my label in IB, and the 30 is a fudge factor (determined empirically) to account for padding above and below the label.
I met the same problems. Unchecking Autolayout can fix it.

Retrieving a UITableViewCell frame

I've frustrated myself with this question for a couple of days. I'm trying to add a UILabel to a UITableViewCell. I want the UILabel to span the entire width of the cell, minus 5 or 10 on both the right and left sides for looks. My problem is in programmatically determining the size of the cell's frame in which to place the label. No matter which UITableViewStyle I use, the cell.contentVew.frame.size.width value is nowhere near the width of the cell frame itself.
For example, in the table I am constructing, I can achieve my desired result by subclassing UITableViewCell and creating a UILabel with a manually determined width (through just trial and error) by:
CGRectMake(10, 12, 397, self.contentView.frame.size.height);
But it's that 397 number that's vexing me. I want a way to programmatically determine what it should be for any width table or style. This should be a simple process by just determining the width of the entire frame of the cell and then subtracting 10 or 20 so the UILabel's edges don't actually touch the edge of the cell.
However, if I set the tableViewStyle to UITableViewStyleDefault and then try:
NSLog(#"Width: %f", self.contentView.frame.size.width);
I get 320. If I set the style to any of the other three styles, the returned number is 302. Even the 320 number isn't anywhere near the width of the cell frame (as with my manually determined number of 397).
What value do I need to access that will return the entire width of the cell's drawing frame? I'm sure, as with most vexing problems, the solution will make me want to slap myself on the forehead, but I'm to the point where I'm ready for it now.
EDIT for more info:
One clarification to anyone interested. This question of mine pertains primarily to a Grouped style table. For a plain style, the answer to my question above can be determined simply in the cellForRowAtIndexPath method by:
CGFloat cellWidth = [tableView rectForRowAtIndexPath:indexPath].size.width;
The problem I'm having is that the rectForRowAtIndexPath method returns the width of the frame in which the cell is drawn, which is fine for a plain style table since the cell width is the entire width of the frame. However, in a grouped table, the width of the cell is less than the width of the frame in which it is drawn, so this method will return a number that is quite a bit wider than the width of the cell. It's possible that the width of the cell in a grouped table style is a fixed number less than the width of the table frame, so this might be the way to solve the problem. I'll investigate that and answer my own question here if that's the case.
I have determined my own answer, and I hope it helps anyone faced with the same issue. The calculation of the margin of a grouped tableView I found on this StackOverflow answer.
This code will provide a label within a tableView cell that spans the cell with a margin between the two edges of the cell, and centered vertically within the cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *label;
CGFloat groupedStyleMarginWidth, tableViewWidth;
UIFont *labelFont = [UIFont boldSystemFontOfSize:17.0]; // Set to whatever you like
NSString *labelText = #"Test String";
// Calculate the margin between the cell frame and the tableView
// frame in a grouped table view style.
tableViewWidth = tableView.frame.size.width;
if (tableView.style == UITableViewStyleGrouped) {
if (tableViewWidth > 20)
groupedStyleMarginWidth = (tableViewWidth < 400) ? 10 : MAX(31, MIN(45, tableViewWidth*0.06));
else
groupedStyleMarginWidth = tableViewWidth - 10;
}
else
groupedStyleMarginWidth = 0.0;
if (cell == nil) {
CGRect tableViewRect;
CGRect labelRect;
CGFloat x, y, w, h, labelMargin;
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Retrieve the rect of the table view.
tableViewRect = [tableView rectForRowAtIndexPath:indexPath];
// Set whatever margin around the label you prefer.
labelMargin = 10;
// Determine rect values for the label.
x = tableRect.origin.x + labelMargin;
// Calculate width of label
w = tableRect.size.width - (groupedStyleMargin * 2) - (labelMargin * 2);
// Calculate height of table based on font set earlier.
h = [labelText sizeWithFont:font].height;
// Calculate y position for the label text baseline to center
// vertically within the cell.
y = (tableRect.origin.y / 2) - (h / 4);
labelRect = CGRectMake(x, y, w, h);
label = [[UILabel alloc] initWithFrame:labelRect];
label.text = labelText;
label.tag = 0;
[cell.contentView addSubview:stepLabel];
[label release];
}
else {
label = (UILabel *)[cell viewWithTag:0];
}
Sounds like this would best be handled by auto layout constraints nowadays.

Resources