UILabel remove bottom margin - objective-c

I am having a trouble with a UILabel.
I am trying to have the UILabel so that there is no margin at all in the container.
I tried different things, like sizeToFit, boundsToRect and others, but never got the solution so far.
Here is my code:
UILabel* saveLabel = [[UILabel alloc] init];
saveLabel = [[UILabel alloc] init];
saveLabel.text = "USER SAVE";
saveLabel.textAlignment = NSTextAlignmentRight;
saveLabel.layer.borderWidth = 2;
[saveLabel sizeToFit];
When I add this to my view I would expect that the border at the bottom (from the border) touch the letter of the labels, but there is a space in between.
I have attached a picture of the bottom effect if you want to see.
http://oi62.tinypic.com/n62b0w.jpg
I really cant understand why this margin is there and how to get rid of it.
All the other margin, top, left and right are fine, just the bottom one.
Any help on this would be very appreciated,
Thanks

The frame includes space for lower case letters like g and y which 'descend' below the text's baseline. In your case, you're only using uppercase letters, so you may wish to remove the descender portion of the frame. You can access the height of the descender via saveLabel.font.descender and then subtract that from the height of the fitted frame.
[saveLabel sizeToFit];
saveLabel.frame = CGRectMake(saveLabel.frame.origin.x
saveLabel.frame.origin.y,
saveLabel.frame.size.width,
saveLabel.frame.size.height - saveLabel.font.descender);
The following article has a good diagram:
https://www.cocoanetics.com/2010/02/understanding-uifont/

Related

How do I create a horizontal line with text in the middle?

I'm very new to Objective C but I'm looking at the source code of an existing app so there's a lot here to sift through.
I'm trying to create something like this:
-------------- or --------------
...only with a solid horizontal line instead of the dashes.
I have the "or" text defined as this:
_orLabel = ^{
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.textColor = [UIColor blackColor];
label.font = [UIFont mainFontWithSize:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline].pointSize];
label.adjustsFontSizeToFitWidth = YES;
label.textAlignment = NSTextAlignmentCenter;
label.text = NSLocalizedString(#"or", nil);
[view addSubview:label];
return label;
}();
That's working great to get "or" to show up but I have no idea how to get the horizontal lines on either side.
I would subclass UILabel and override drawTextInRect:. The easiest way is to call super so that the text gets drawn. Now you are still in a graphics context (CGContext) so you can use ordinary Quartz drawing commands to draw your horizontal lines.
The simplest approach is to make use of certain Unicode characters that will give you a solid line.
label.text = #"───────── or ─────────";
That text is using a series of "BOX DRAWINGS LIGHT HORIZONTAL" characters (U+2500).
I would use IB to add a view on each side of the label. Make the views have a height of 1 or 2 with a black background, and use autolayout to make them size appropriately for the label and screen situation:
Make view #1 anchored to the left edge of the screen and the right side of the label.
Make view #2 anchored to the right edge of the screen and the left side of the label.
Make the 2 views and the label have the same vertical center.

How to find the position of the last text line in a multiline UILabel or otherwise have UILabel have 0 padding

I have a UILabel that has both -numberOfLines set to 3 and text-size auto shrink and I need to align another UIView to this UILabel's last line of text. That is, I might need to align to the y position of line 0, 1 or 2, depending on the text inside the label (and the distance between these lines of text may vary depending on whether the text is long enough that it triggered font resizing).
But:
UILabel doesn't expose a contentSize
the label's bounds extend past the last line of text (there seems to be a content inset), so aligning to the bounds won't work.
subclassing UILabel and doing something like this:
- (void)drawTextInRect:(CGRect)rect {
UIEdgeInsets insets = {0., 0., -30., 0.};
return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
just happens to work for the case where I have 3 lines and the font size was auto shrunk, but I still can'r figure out a generic way of subtracting insets for the general case, regardless of text size. And I don't seem to be able to use -boundingRectWithSize:options:context: either: it either returns a single line equivalent rect or, If I play around with the options, a a rect the same size of the original label (that is, including the extra insets I'm trying to get rid of). Mind you, the idea behind removing any insets is that if I have no way of knowing where the last line of text is, at least I can remove any insets in the label so that the last line of text aligns with the label's bounds.origin.y + bounds.size.height.
Any thoughts?
I don't know if the problem was that originally I was using boundingRectWithSize on non-attributed text or what but now this seems to work:
NSString *text = <get text from CoreData>;
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:#{NSFontAttributeName: self.titleLabel.font}];
CGRect rect = [attributedText boundingRectWithSize:self.titleLabel.frame.size
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
if (!rect.size.height || rect.size.height > self.titleLabel.frame.size.height) {
attributedText = [[NSAttributedString alloc] initWithString:text attributes:#{NSFontAttributeName: [UIFont boldSystemFontOfSize:self.titleLabel.font.pointSize * self.titleLabel.minimumScaleFactor]}];
rect = [attributedText boundingRectWithSize:self.titleLabel.frame.size
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
}
self.titleLabel.frame = rect;
self.titleLabel.attributedText = attributedText;
While this doesn't really find the position of the bottom of the last line of text in the UILabel (the label still adds some padding at the bottom... not sure if to account for descenders), it adjusts the label's bounds close enough to the bottom that I can at least align based on bounds.origin.y + bounds.size.height and it looks good enough.

Creating a dropshadow for UITableView

Would somebody please explain how to create a one or two pixel drop shadow ONLY on the the very last cell (in other words, I don't want a shadow around the entire tableview, just the bottom cell. An image of what I'm talking about:
Solved. Use the following code to produce a very nice, subtle shadow to the bottom of your UITableViewCell. Makes it look like it's raised slightly out of the page :)
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(3, 49, cell.frame.size.width-26, 3)];/// change size as you need.
separatorLineView.backgroundColor = shadowColor;// you can also put image here
UIBezierPath *roundedShadow = [UIBezierPath bezierPathWithRoundedRect:separatorLineView.bounds byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(8.0f, 8.0f)];
CAShapeLayer *newSeparatorShape = [[CAShapeLayer alloc] init];
[newSeparatorShape setPath:roundedShadow.CGPath];
separatorLineView.layer.mask = newSeparatorShape;
[cell.contentView addSubview:separatorLineView];
Also, don't forget to put this at the top of your .m file #import <QuartzCore/QuartzCore.h>
You could, in tableView:cellForIndexPath: set the cell's background image to one that includes the rounded corners with the shadow.

Vertical line in front of text in a UILabel. Like blockquotes

I'm building a small app and wan't to display quotes in a UITableView. I'm using custom UITableViewCells with a bunch of UILabels, one for the headline and one for quote and more labels for more information.
I want to display the quote with a vertical line on the left side in front of the text. Like some blockquotes. Here is an example from Reeder-App, it does it exactly the way I want it.
Is there a simple way to do this, maybe with attributed strings? A hint would be awesome, because I haven't got an idea to solve it.
Get the textheight like:
CGSize textHeight = [textLabel.text sizeWithFont:textLabel.font constrainedToSize:CGSizeMake(textLabel.frame.size.width, 99999999)];
Then draw the line like:
UIView *lineView = [[UIView alloc]initWithFrame:CGRectMake(10, 10, 5, textHeight.height)];
lineView.backgroundColor = [UIColor grayColor];
[self.view addSubview:lineView];

reproduce UITableViewCellSeparatorStyleSingleLineEtched in UITableViewStylePlain

How can one reproduce the same effect as Single Line Etched when using plain table and custom cells?
I think I need to add them as subview to each cell, excluding the last one. I want to know how to reproduce that without having to use images to that. Does anyone know?
Isn't the separator just a single pixel grey line, even for Single Line Etched?
In this case, create a UIView the width of the cell, but only one pixel high and then set it's background colour,then stick it at the bottom of the cell's content view.
UIView *lineView;
lineView = [[UIView alloc] initWithFrame:CGRectMake(0.0f,
cell.contentView.bounds.size.height-1.0f,
cell.contentView.bounds.size.width,
1.0f);
lineView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
lineView.backgroundColor = [UIColor grayColor];
[cell.contentView addSubview:lineView];