Creating UILabel programmatically with dynamic size - ios

I am trying to create UILabel programmatically, but height and width should be set dynamically depending on the content. I don't want to create initial CGRect with some width and height, which cause design issues in my case.
What I tried to do is:
self.freeLabel = [[UILabel alloc] initWithFrame:CGRectMake(frameView.layer.frame.size.width - 50, -8, 120, 25)];
self.freeLabel.numberOfLines = 0;
[self.freeLabel setBackgroundColor:[UIColor colorWithRed:0.91 green:0.18 blue:0.42 alpha:1.0]];
self.freeLabel.layer.cornerRadius = 5;
self.freeLabel.layer.masksToBounds = YES;
[self addSubview:self.freeLabel];
[self sizeToFit];
but this way I cannot add the UILabel to my view.

you have to add below codes so that self.freeLabel with take new height.
[self.freeLabel sizeToFit];
self.freeLabel.frame = CGRectMake(frameView.layer.frame.size.width - 50, -8, 120, self.freeLabel.frame.size.height)];
self.frame = // update size based on the height of the label.
But I have some points which I feel are wrong.
Why x position of self.freeLabel is defined as frameView.layer.frame.size.width - 50 but width of label as 120. For sure this label will go out of your view. So frameView.layer.frame.size.width - 50 should be frameView.layer.frame.size.width - 120

Related

UIButton width or line break mode problem

I'm programmatically adding UIButton objects to an UIScrollView. The result I'm getting is that the height of the button is calculated properly, i.e. there is a space for a second line, but the text does not wrap, it rather continues to flow as if the button has infinite width. I used to have UITextView objects instead of the buttons, and that worked flawlessly. I just cannot set the buttons to layout the same way the text views did.
Here's a code snipplet:
UIButton* sButton = [[UIButton alloc] initWithFrame:CGRectMake(0, yPos, sWidth - 5, height)];
sText = [[NSMutableString alloc] initWithString:#"quite a long string that does not fit in one line, no chance"];
sButton.titleLabel.font = font;
sButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[sButton setLineBreakMode:NSLineBreakByWordWrapping];
[sButton.titleLabel setLineBreakMode:NSLineBreakByWordWrapping];
[sButton setTitle:sText forState:UIControlStateNormal];
[sButton sizeToFit];
And this is the result I'm getting:
How can I make the button text wrap?
This is the only solution I've found that works: https://stackoverflow.com/a/4978003/963022
I ended up creating a custom button implementation and overriding:
- (CGSize)sizeThatFits:(CGSize)size {
int diff = 0;
// for the width, subtract DIFF for the border
// for the height, use a large value that will be reduced when the size is returned from sizeWithFont
CGSize tempSize = CGSizeMake(size.width - diff, 1000);
CGSize stringSize = [self.titleLabel.text
sizeWithFont:self.titleLabel.font
constrainedToSize:tempSize
lineBreakMode:UILineBreakModeWordWrap];
return CGSizeMake(size.width - diff, stringSize.height);
}

Rotate a UIlabel to make it vertical

I have a UILabel. I need to rotate it programmatically.
I have my horizontal UILabel, for example with frame: x:0, y:0, w: 200, h:80.
Now I would like to rotate the label to make it vertical:
I try this code:
[self setTransform:CGAffineTransformMakeRotation(M_PI_2 / 2)];
I can see the contained text rotated. But I would like to rotate the whole frame: With my code, the UILabel continues to have the same frame.
Try this working code:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, 200, 80)];
//set background color to see if the frame is rotated
[label setBackgroundColor:[UIColor redColor]];
[label setText:#"Text Here"];
label.transform=CGAffineTransformMakeRotation( ( 90 * M_PI ) / 180 );
[self.view addSubview:label];
Hope it helps
If you prefer set the label position and size visually in you xib or storyboard do the following:
Set the labels position and size in the interface builder like you want them to stay after the rotation.
Rotate the label and set the frame again:
-(void)rotateLabel:(UILabel*) label
{
CGRect orig = label.frame;
label.transform=CGAffineTransformMakeRotation(M_PI * 3/2);//270º
label.frame = orig;
}
Your Label is a square(w:100,h:100).So your label has transformed, but you can't see the change,because the width is equal to the height.

UIImageView and autolayout

I have a view that is set up nicely using autolayout. The view contains a series of labels stacked from top to bottom. I am allowing the intrinsic size of these labels to determine the size of the view.
The final step is to add a background from an image. I started by trying the colorWithPatternImage method on UIColor but this isn't quite what I am looking for. I do not want to tile the image, and I can not guarantee it will always be larger than the intrinsic size of the view.
Similarly, adding a uiImageView to the view itself doesn't quite work. The view will expand to accommodate the image when I want to keep the intrinsic size based on the labels.
I guess what I am looking for is the following.
1) The background should have no effect on the size of the view.
2) The image should be scaled to fill the view but in it's original aspect ration (so cropping edges if necessary).
Any ideas appreciated.
In my case, I needed it for a UIImageView inside a dynamically-sized view in a UITableViewCell, but the image refused to shrink below its instristic size and instead worked as a minimum-size constraint for the superview. The only way I could get it ignore the intristic size is by lowering the priority at which it is enforced, right after creating the cell:
[imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
[imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisVertical];
After this, all my constraints magically started working. In the OP's case, setting UIViewContentModeScaleAspectFill is also required, as per Mundi's answer.
In Interface Builder, add a UIImageView as the first subview to the view. Make sure its size always matches the view.
Then, in Interface Builder or code, set the contentMode:
backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
Here's how I would approach this. Hopefully it helps. :)
CGRect contentFrame = CGRectMake(0, 0, self.view.frame.size.width, 0); // This will be the frame used to create the background image view.
UIEdgeInsets contentInsets = UIEdgeInsetsMake(20, 20, 20, 20); // The margins by which the labels will be inset from the edge of their parent view.
CGFloat labelHeight = 21;
CGFloat verticalGap = 8; // The vertical space between labels
CGFloat y = contentInsets.top;
int numberOfLabels = 10;
for (int i = 0; i < numberOfLabels; i++) {
CGRect frame = CGRectMake(contentInsets.left, y, self.view.frame.size.width - (contentInsets.left + contentInsets.right), labelHeight);
UILabel *label = [[[UILabel alloc] initWithFrame: frame] autorelease];
// customize the label here
[self.view addSubview: label];
contentFrame = CGRectUnion(contentFrame, label.frame);
y += labelHeight + verticalGap;
}
contentFrame.size.height += contentInsets.bottom;
UIImageView *backgroundImageView = [[[UIImageView alloc] initWithFrame: contentFrame] autorelease];
[backgroundImageView setClipsToBounds: YES];
[backgroundImageView setContentMode: UIViewContentModeScaleAspectFill];
[backgroundImageView setImage: [UIImage imageNamed: #"background_image.png"]];
[self.view insertSubview: backgroundImageView atIndex: 0];

Dynamically Creating and Positioning UILabels of Different Sizes

I am creating dynamic UILabels and then adding them to the view. The labels are in vertical layout. Like this:
Label 1
Label 2
Label 3
Each label can be of different height. So in order to accomodate the height I use the following code. The Label 2 uses Label 1 position and height to adjust itself on the view.
-(void) createAboutLabel
{
self.aboutLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.nameLabel.frame.origin.x, self.nameLabel.frame.origin.y + self.nameLabel.frame.size.height, self.view.frame.size.width - 10, 40)];
self.aboutLabel.text = self.selectedVegetableCategory.about;
self.aboutLabel.font = [Utility getFont:#"Sinhala Sangam MN" size:14];
// [self.aboutLabel sizeToFit];
[self.aboutLabel setNumberOfLines:0];
[self.aboutLabel setLineBreakMode:UILineBreakModeWordWrap];
[self.aboutLabel sizeToFit];
[self.scrollView addSubview:self.aboutLabel];
}
I am trying to find a better way of achieving the dynamic label layout.
Any suggestions?
By passing width & font, height can be retrieved -
NSString *theText = myLabel.text;
CGFloat width = myLabel.frame.size.width ;
CGSize theSize = [theText sizeWithFont:myLabel.font constrainedToSize:CGSize(width,MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
It will return the size from that extract height.
CGFloat myLabelHeight = theSize.height;
Hope this should help.

How to center a UILabel on UIView

How can I center the UILabel on the UIView? I am using the following code
float width = weatherView.bounds.size.width;
float height = weatherView.bounds.size.height;
[self.label setFrame:CGRectMake(width-100,height-100, 100, 100)];
How about:
[self.label setCenter:view.center];
If the label is a subview of view:
[self.label setCenter:CGPointMake(view.frame.size.width / 2, view.frame.size.height / 2)]
Don't use view.center unless the label and view have the same superview.
If there is no immediate connection, then you'll have to transform view's center to the coordinate space of label's parent. Then you could use PengOne's answer with the transformed point.
Use NSTextAlignmentCenter if what you have is the label already set and you want to center its content.
cell.menuLabel.textAlignment = NSTextAlignmentCenter;
A better posible solution is:
First: If you are doing this programmatically you'll need to initialize with frame and some customizations:
// Simple example
int yPosition = 10;
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(0, yPosition, self.view.frame.size.width, 0)];
[label setText: #"Testing..."];
[label setBackgroundColor: [UIColor clearColor]];
[label setNumberOfLines: 0];
[label sizeToFit];
Second: If a label what you are trying to center you can just run this after setNumberOflines selector called and 0 value assigned, your text will have all lines needed, and sizeToFit method called to have a good customization, and finally:
[self.label setCenter: CGPointMake(self.view.center.x, self.label.center.y)];
This will center only the X axis, and the Y axis will stay as you desired in the frame initialization.
PS: It's also valid if not a UILabel but depends on the control you are using will need another simple customization or neither, and if you only want to center programmatically but interface builder designed, just need to run the second code.
PengOne / Alex Lockwood's answer is simple and useful. If you intend to support rotation, add the following to keep it centered:
[self.myLabel setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth];
Something like this should do the trick...
Make sure that your label is set to have centered alignment and is sufficiently big/wide to handle your text string.
float viewWidth = weatherView.frame.size.width;
float viewHeight = weatherView.frame.size.height;
float labelWidth = label.frame.size.width;
float labelHeight = label.frame.size.height;
float xpos = (viewWidth/2.0f) - (labelWidth/2.0f);
float ypos = (viewHeight/2.0f) - (labelHeight/2.0f);
[label setFrame:CGRectMake(xpos,ypos,labelWidth,labelHeight)];
I think that should do what you are asking for.
There are two possibility if your UILabel is added via .xib or else added programmatically .
If first case i.e added via .xib then you can set the position from xib file size inspector tab with the 'Arrange' property
And if second case persist then you can set as --- [self.label setCenter:view.center];

Resources