How to arrange dynamically created UILabels inside UIView? [closed] - ios

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am dynamically creating UILabels from an array using a for loop.
Each UILabel has a different length. When I created the UILabels, they are overlapping one another.
I want to arrange those UILabels properly inside the UIView without any overlapping. Any help?

You can find how it works here: arrange labels sources link
Download sources using appropriate button on site
Open ArrangeLabels project
Open ViewController.m file
Check -createElements -fitElements methods from the sources.
If you want you can view sources here immediately in your browser: link to code

You can do it using sizeToFit and numberOfLines=0
int y=0;
for (int k=0; k<[array count]; k++)
{
UILabel *lb=[[UILabel alloc]initWithFrame:CGRectMake(5 , y, 100,60)];
lb.textAlignment=UITextAlignmentLeft;
lb.text=[array objejectAtIndex:k];
lb.numberOfLines=0;
[lb sizeToFit];
[self.view addSubview:lb];
y+=lb.frame.size.height;
}

Try to implement this logic:
-(void)adjustLabel1Text1:(NSString *)text1
{
UILabel *lbl_first = [UIFont fontWithName:#"Helvetica" size:12];
text1 = [text1 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
float hedingLblHeight = [self calculateHeightOfTextFromWidth:text1 : [UIFont fontWithName:#"Helvetica" size:12] :118 :UILineBreakModeWordWrap];
lbl_first.text=text1;
[lbl_first setFrame:CGRectMake(lbl_first.frame.origin.x, lbl_first.frame.origin.y, 118, hedingLblHeight)];
lbl_first.lineBreakMode = UILineBreakModeWordWrap;
lbl_first.numberOfLines = 0;
[lbl_first sizeToFit];
//////////Adjust the lable or any UIControl below this label accordingly.
float endResultHeight=[self calculateHeightOfTextFromWidth:text2 : [UIFont fontWithName:#"Helvetica" size:15] :299 :UILineBreakModeWordWrap];
if(hedingLblHeight>secondImgTitleHeight)
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
else
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
lbl_endResult.lineBreakMode=UILineBreakModeWordWrap;
lbl_endResult.numberOfLines = 0;
[lbl_endResult sizeToFit];
}
-(float) calculateHeightOfTextFromWidth:(NSString*)text : (UIFont*) withFont:(float)width :(UILineBreakMode)lineBreakMode
{
CGSize suggestedSize = [text sizeWithFont:withFont constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:lineBreakMode];
return suggestedSize.height;
}
It has helped me a lot.Hope it works for you.

You need to change y coordinate of your label like this
UILabel *hiLbl = [[UILabel alloc] initWithFrame:CGRectMake(0,10,50,20)];
hiLbl.text = #"Hi";
[self.view addSubview:hiLbl];
UILabel *hellolbl = [[UILabel alloc] initWithFrame:CGRectMake(0,30,50,20)];
hellolbl.text = #"Hi";
[self.view addSubview:hellolbl];
or
UILabel *lbl;
for(int i = 1 ; i < 3 ; i++)
{
lbl = [[UILabel alloc] initWithFrame:CGRectMake(0,i*10+10,50,20)];
[self.view addSubview:lbl];
lbl.text = i;
}

Without any screenshot it is difficult to guess what type of overlapping you are referring to. And length of UILabel does not help, either specify- width or height.
But if you are talking about width of UILabel, then this piece of code may help you.
Lets you have three labels of different widths, which are in an array of widths array:{ 10, 20, 30}.
float width = [array objectAtIndex:0];
float x = 0.of;
float padding = 10.0f;
for(int i =0; i<3; i++){
UILabel *label = [UILabel alloc]initWithFrame:CGRectMake(x, y, width, height)];
[self.view addSubview: label];
x = x + width + paddng;
width = [array objectAtIndex:i + 1];
}

Related

iOS - addSubview without overlap

In a for loop, I'm trying to add Labels to a ScrollView based on a number given by the user. Here is the code in Objective-C:
NSInteger numberOfViews = [self.textfieldNumViews.text intValue];
for (int i = 0; i < numberOfViews ; i++){
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 300, 12)];
label.text = [NSString stringWithFormat:#"%d",i];
label.backgroundColor = [UIColor lightGrayColor];
[self.scrollviewViewContainer addSubview:label];
}
The problem is that the labels are overlapping each other inside the ScrollView, when I really want them to just display one after the other.
Image I understand that this is due to how addSubview behaves, placing views on top of other views, but is there any way I can prevent that? Or some other function I could use? I feel like this should be an easy task but I can't seem to figure it out. Is there something like a vertical layout property I can add to the ScrollView? Or add margins to the labels?
You need to set the y lower for each subview. Check the third line:
NSInteger numberOfViews = [self.textfieldNumViews.text intValue];
for (int i = 0; i < numberOfViews ; i++){
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(0, (i*20), 300, 12];
label.text = [NSString stringWithFormat:#"%d",i];
label.backgroundColor = [UIColor lightGrayColor];
[self.scrollviewViewContainer addSubview:label];
}

Create controls in UIView at runtime?

I have one UITextField and a button in a view.
Once a button is pressed, value in text field need to be searched fieldID column in core data table and get value[comma separated].
Separate the string by comma and assign values to array.
A new UIView needs to be inserted in the main screen and place N number[count of array] of labels and textfields and align.
I am able to do 1, 2 and UIView creation.
Can anybody help me to create N number of controls in sub UIView at runtime?
for(int i=0;i<self.yourArray.count; i++)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10,80*i+60,self.view.frame.size.width-20,60)];
label.text = [yourArray objectAtIndex:i];
[self.view addSubview:label];
}
Please Explain your problem more clearly !
May be your array count is very large so take a scroll view also in your view
UIScrollView* yourScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(yourView.frame.origin.x, yourView.frame.origin.y,yourView.frame.size.width,yourView.frame.size.height)];
for(int i= 0; i< 10;i++)
{
UILabel* lbl = [[UILabel alloc]initWithFrame:CGRectMake(10, y, 50, 21)];
lbl.text = #"";
UITextField* txtField = [[UITextField alloc]initWithFrame:CGRectMake(lbl.frame.origin.x+10 , y, 200, 21)];
txtField.text = #"";
[yourScrollView addSubview:lbl];
[yourScrollView addSubview:txtField];
y = y+30;
}
[yourView addSubview:yourScrollView];

How to customze UISlider to get stepps visible

I want to customize my UISlider to be able to show steps like in photo attached (BTW this is a font size selector, native control from my iPhone settings). I able to set images for min and max but I can't show steps. I don't need 3rd party libraries to do this, I'm sure that it's possible to customize UISlider to have this.
Please help.
Thanks in advance.
You can add some subviews behind the slider to display the steps:
int numSteps = 5;
for(int i=0; i<numSteps; i++){
CGFloat x = i*CGRectGetWidth(slider.frame)/(numSteps-1);
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(x, CGRectGetMidY(slider.frame)-5, 1, 10)];
v.backgroundColor = [UIColor lightGrayColor];
[slider.superview insertSubView:v belowSubview:slider];
UILabel numberLabel = [[UILabel alloc] init];
numberLabel.text = [NSString stringWithFormat:#"%i",i];
numberLabel.font = [UIFont systemFontOfSize:13];
[numberLabel sizeToFit];
numberLabel.center = CGPointMake(x, CGRectGetMidY(slider.frame)+CGRectGetHeight(numberLabel.frame)/2+7);
[slider.superview insertSubView:numberLabel belowSubview:slider];
}

create a set of UITextViews that are dynamically sized and laid out in place in relation to each other

I have a custom UIView where I want to layout a set of UITextView's in response to an AJAX call. So I think I will need to create these in code. I am currently setting the location to a fixed location but would rather set it to like 20pixels below the previous one. Also, I would like to set a minimum width of 650 pixels of my UITextView. I am using AutoLayout but am confused about the best way to achieve this. I have included my code but am really looking for what strategy is best to achieve this? Use AutoLayout constraints?
I have include how I'm currently doing it but would like to solve the dynamic verticasl placement and a fixed width of the UITextView's to 650points. Any help either in strategy or code would be greatly appreciated.
for (int i = 0; i < [some count]; i++) {
int my_counter=i+1;
// this is obviously putting it a fixed location
UITextView *textview= [[UITextView alloc]initWithFrame:CGRectMake(110, (130 * my_counter), 650, 90)];
[textview setScrollEnabled:YES];
textview.layer.borderWidth = 5.0f;
textview.layer.borderColor = [[UIColor grayColor] CGColor];
[textview setTextContainerInset:UIEdgeInsetsMake(7, 7, 7, 7)];
NSString *tmp_header=[some[i] objectForKey:#"header"];
NSString *tmp_body=[some[i] objectForKey:#"body"];
//NSString *str = #"This is <font color='red'>simple</font>";
if(![tmp_header isEqualToString:#""] && ![tmp_body isEqualToString:#""]){
NSString *myString=[NSString stringWithFormat:#"%# \n %#", tmp_header, tmp_body];
[textview setValue:myString forKey:#"contentToHTMLString"];
}
if([tmp_header isEqualToString:#""] && ![tmp_body isEqualToString:#""]){
[textview setValue:#"body is cool" forKey:#"contentToHTMLString"];
}
textview.textAlignment = NSTextAlignmentLeft;
textview.editable = NO;
textview.font = [UIFont fontWithName:#"vardana" size:20.0];
[textview sizeToFit];
[textview setScrollEnabled:NO];
//textview.contentSize.width=650;
[self.noteView addSubview:textview];
}
Generally, with this kind of problem you need to keep track of something outside the loop, to pass previous results to the next loop iteration. This code should work:
CGFloat runningYPosition = 130.f; // Y position of first text view
for (int i = 0; i < 10; i++) {
// Let's not care about the text view frame right now.
// Let's just create, configure, populate, then set a frame based on contents/configuration.
UITextView *textview= [[UITextView alloc]initWithFrame:CGRectZero];
textview.layer.borderWidth = 5.0f;
textview.layer.borderColor = [[UIColor grayColor] CGColor];
[textview setTextContainerInset:UIEdgeInsetsMake(7, 7, 7, 7)];
NSString *tmp_header=[some[i] objectForKey:#"header"];
NSString *tmp_body=[some[i] objectForKey:#"body"];
//NSString *str = #"This is <font color='red'>simple</font>";
if(![tmp_header isEqualToString:#""] && ![tmp_body isEqualToString:#""]){
NSString *myString=[NSString stringWithFormat:#"%# \n %#", tmp_header, tmp_body];
[textview setValue:myString forKey:#"contentToHTMLString"];
}
if([tmp_header isEqualToString:#""] && ![tmp_body isEqualToString:#""]){
[textview setValue:#"body is cool" forKey:#"contentToHTMLString"];
}
textview.textAlignment = NSTextAlignmentLeft;
textview.editable = NO;
textview.font = [UIFont fontWithName:#"vardana" size:20.0];
// Set the text view frame
CGSize textViewSize = [textview sizeThatFits:CGSizeMake(650.f, CGFLOAT_MAX)];
textview.frame = CGRectMake(110.f, runningYPosition, textViewSize.width, textViewSize.height);
[self.view addSubview:textview];
// Update the running Y position for the next text view's frame, 20 pts below the current one.
runningYPosition = CGRectGetMaxY(textview.frame) + 20.f;
}
I think you could do it as a UITableView. Each new item would be added to the tableview's data array and you could use [tableView reloadData] to display the new item.
You could then use
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
to adjust the height of each cell individually.

Center vertically in UILabel with autoshrink

This is a little different from all the other "How do I center the text in a UILabel" questions here...
I have a UILabel with some text in it, I want to center the text vertically in the UILabel. What's the big deal, right? That's the default. The problem comes because my text is dynamic and I have autoshrink turn on. As the text grows larger, the font size shrinks. You get this behavior.
Notice that the font baseline has not moved, I want it to move so the numbers are centered vertically in the UILabel's frame.
Easy, right? I just remember the frame's original center in viewDidLoad
self.workoutTimeCenter = _workoutTimeLabel.center;
and then I call sizeToFit after I change the the text, right?
[_workoutTimeLabel sizeToFit];
_workoutTimeLabel.center = _workoutTimeCenter;
Well, sizeToFit did, I guess, exactly what it was supposed to do, resize the frame so the text fits without shrinking!
How can I vertically center the text in a UILabel while respecting baselines and autoshrink? (Note, an iOS5 and later solution is fine and I can even deal with an iOS6 and later solution.)
In my experience you can just set the -[UILabel baselineAdjustment] property to UIBaselineAdjustmentAlignCenters to achieve the effect you're describing.
From the docs:
baselineAdjustment
Controls how text baselines are adjusted when text
needs to shrink to fit in the label.
#property(nonatomic) UIBaselineAdjustment baselineAdjustment
Discussion
If the adjustsFontSizeToFitWidth property is set to YES,
this property controls the behavior of the text baselines in
situations where adjustment of the font size is required. The default
value of this property is UIBaselineAdjustmentAlignBaselines. This
property is effective only when the numberOfLines property is set to
1.
and
UIBaselineAdjustmentAlignCenters
Adjust text based relative to the center of its bounding box.
EDIT: adding a full view-controller that demonstrates this:
#interface TSViewController : UIViewController
#end
#implementation TSViewController
- (void) addLabelWithFrame: (CGRect) f baselineAdjustment: (UIBaselineAdjustment) bla
{
UILabel* label = [[UILabel alloc] initWithFrame: f];
label.baselineAdjustment = bla;
label.adjustsFontSizeToFitWidth = YES;
label.font = [UIFont fontWithName: #"Courier" size: 200];
label.text = #"00";
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor lightGrayColor];
label.userInteractionEnabled = YES;
[self.view addSubview: label];
UIView* centerline = [[UIView alloc] initWithFrame: CGRectMake(f.origin.x, f.origin.y+(f.size.height/2.0), f.size.width, 1)];
centerline.backgroundColor = [UIColor redColor];
[self.view addSubview: centerline];
UITapGestureRecognizer* tgr = [[UITapGestureRecognizer alloc] initWithTarget: self action: #selector(onTap:)];
[label addGestureRecognizer: tgr];
}
- (void) viewDidLoad
{
[super viewDidLoad];
[self addLabelWithFrame: CGRectMake(0, 0, 320, 200)
baselineAdjustment: UIBaselineAdjustmentAlignCenters];
[self addLabelWithFrame: CGRectMake(0, 220, 320, 200)
baselineAdjustment: UIBaselineAdjustmentAlignBaselines];
}
- (void) onTap: (UITapGestureRecognizer*) tgr
{
UILabel* label = (UILabel*)tgr.view;
NSString* t = [label.text stringByAppendingString: #":00"];
label.text = t;
}
#end
when working in IB, be sure to set align baselines to center
Note: line break CANNOT be word wrap for this to work, so it will NOT work multiline (good to set the line break to Truncate tail)
-(void)fitVerticallyToLabel:(UILabel *)lbl
{
CGFloat fontSize = lbl.frame.size.width / lbl.text.length;
[lbl setFont:[UIFont fontWithName:#"Helvetica-Bold" size:fontSize]];
CGRect rect = lbl.frame;
rect.origin.y += rect.size.height - fontSize;
rect.size.height = fontSize;
[lbl setFrame:rect];
}
How to Use: Call this method after setting the text to your label.
label.text = #"text";
[self fitVerticallyToLabel:label];
Note: I ahev taken UILabel from xib. You can take it programmatically too in that case you will have to set its text alignment NSTextAlignMentCenter
Try to implement this logic:
-(void)adjustLabel1Text1:(NSString *)text1
{
UILabel *lbl_first = [UIFont fontWithName:#"Helvetica" size:12];
text1 = [text1 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
float hedingLblHeight = [self calculateHeightOfTextFromWidth:text1 : [UIFont fontWithName:#"Helvetica" size:12] :118 :UILineBreakModeWordWrap];
lbl_first.text=text1;
[lbl_first setFrame:CGRectMake(lbl_first.frame.origin.x, lbl_first.frame.origin.y, 118, hedingLblHeight)];
lbl_first.lineBreakMode = UILineBreakModeWordWrap;
lbl_first.numberOfLines = 0;
[lbl_first sizeToFit];
//////////Adjust the lable or any UIControl below this label accordingly.
float endResultHeight=[self calculateHeightOfTextFromWidth:text2 : [UIFont fontWithName:#"Helvetica" size:15] :299 :UILineBreakModeWordWrap];
if(hedingLblHeight>secondImgTitleHeight)
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
else
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
lbl_endResult.lineBreakMode=UILineBreakModeWordWrap;
lbl_endResult.numberOfLines = 0;
[lbl_endResult sizeToFit];
}
-(float) calculateHeightOfTextFromWidth:(NSString*)text : (UIFont*) withFont:(float)width :(UILineBreakMode)lineBreakMode
{
CGSize suggestedSize = [text sizeWithFont:withFont constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:lineBreakMode];
return suggestedSize.height;
}
It has helped me a lot.Hope it works for you.
Try
yourLabel.textAlignment = UITextAlignmentCenter;

Resources