Displaying UILabel dynamcially from the NSMutableArray - ios

I have a mutable array as below
labelArrays = [NSMutableArray arrayWithObjects:#"One”, #“Two”, #“Three", nil];
I want to display all the list array values as individual label. This is like displaying the UILabel dynamically using the array values. What i did is as below,
int count=20;
for(int i = 0; i < [labelArrays count]; i++){
label1 = [[UILabel alloc]init];
label1.text = [labelArrays componentsJoinedByString:#" "];
label1.textColor = [UIColor colorWithRed:0.643 green:0.643 blue:0.639 alpha:1];
label1.layer.borderWidth = 1.0;
label1.layer.cornerRadius = 8;
count+=20;
[self addSubview:label1];
}
Here I can only display all the array values inside the single label. How can i display the array values in multiple labels dynamically.
//viewcontroller
myView.label1.frame =CGRectMake(588,200,200,28);

your coding is fine , but you are not added the frame , try this
label1 = [[UILabel alloc] initWithFrame: CGRectMake(0,count,aslikeyourwidth,aslikeyourheight)];

Define a public method for view in which you are willing to add the UILabel, pass a CGRect to that method and then according to your design, with each iteration update the x coordinate or y coordinate. Follow the below steps:
// code in your viewcontroller
[myView designYourMultipleLabelsWithStartingFrame:CGRectMake(588,200,200,28)]; // pass the frame of the first label.
Now add the multiple UILabel in your view class, let's assume you have set labelArrays.
// code in view class
-(void) designYourMultipleLabelsWithStartingFrame:(CGRect) frame{
float xCoordinate = frame.origin.x;
float yCoordinate = frame.origin.y;
for(int counter = 0; counter < [labelArrays count]; counter++){
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(xCoordinate,yCoordinate,labelWidth,labelHeight)];
label.text = [labelArrays objectAtIndex:counter];
[self addSubview:label];
// update the x coordinate or y coordinate according to your design. Let's say we need the labels in vertical order, so update the y Coordinate by labelHeight and gap between two labels.
yCoordinate = yCoordinate + labelHeight + gapBetweenTwoLabels.
}
}
Hope this will help.

Just a thought - would you not be better using a tableview to show the array?
It looks like you may need to just handle their position on the view as the code looks like it is adding the labels but it is placing them over each other.

Related

How to set alignment for UIScrollView in ios

i am creating an application, where i am using UIScrollView for displaying the number of available colors of each product. I am getting number of available colors at run time, so i have used for loop and displaying on my scroll view. Its working fine, but the problem if i am getting only one available color then my output is coming as below screen :
But the output should be as below screen :
It seems like i need to do kind of center alignment for my UIScrollView, so every available color will suppose to display from center. here is my code :
UIScrollView *availableColorScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 80)];
availableColorScrollView.backgroundColor = [UIColor clearColor];
availableColorScrollView.showsHorizontalScrollIndicator = YES;
availableColorScrollView.showsVerticalScrollIndicator=NO;
availableColorScrollView.pagingEnabled = YES;
for (int i = 0; i < arrayAvlbleColors.count; i++) {
CGRect frame;
frame.origin.x = 23 * i;
frame.origin.y = 0;
frame.size = availableColorScrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
UILabel *label = [[UILabel alloc] init];
[label setFrame:CGRectMake(15, 14, 16, 16)];
[label.layer setCornerRadius:8];
NSString *strColorCode = [arrayAvlbleColors objectAtIndex:i];
strColorCode = [strColorCode substringFromIndex:1];
[label setBackgroundColor:[self colorWithHexString:strColorCode]];
[subview addSubview:label];
[availableColorScrollView addSubview:subview];
}
[self.view addSubview:availableColorScrollView];
availableColorScrollView.contentSize = CGSizeMake(24 * arrayAvlbleColors.count, availableColorScrollView.frame.size.height);
Please suggest me to achieve my output, Thanks!
this is the simple answer but working fine if u taken any Mainview or subview or else,
set the frame size/2 for height and width it automatically set it into center of the subview.
here i used static color , customize urself
just change your line this
NSString *strColorCode = [arrayAvlbleColors objectAtIndex:i];
strColorCode = [strColorCode substringFromIndex:1];
[label setBackgroundColor:[self colorWithHexString:strColorCode]];
[subview addSubview:label];
[availableColorScrollView addSubview:subview];
into
NSString *strColorCode = [arrayAvlbleColors objectAtIndex:i];
strColorCode = [strColorCode substringFromIndex:1];
[label setBackgroundColor:[self colorWithHexString:strColorCode]];
//use any one
//option no 1:
//[label setCenter:subview.center];
//option no 2:
[ label setCenter:CGPointMake(subview.frame.size.width / 2, subview.frame.size.height / 2)];
[subview addSubview:label];
[availableColorScrollView addSubview:subview];
final out put is
You can calculate your scrollview content to be placed in centre like this:
float contentWidth = 23 * arrayAvlbleColors.count;
Now you have content width to subtract from scrollView's width
float centerPadding = 0.0f;
float width = availableColorScrollView.frame.size.width;
centerPadding = width - contentWidth;
if(centerPadding < 0)
{
//content cannot be placed in center as content is bigger than width
centerPadding = 0.0f;
}
We have padding to center our content in scrollView, so use it in for loop like this :
frame.origin.x = (23 * i) + centerPadding;

Adding UILabels to UIView dynamically

I have a web service that brings some text data back. The idea is to extract the text and create UILabels for the text to show on screen. I however, do not know two things:
How many labels are needed
The length of the text
Due to having no prior knowledge of these things I need a way to create some labels that have the right length for the text it contains.
I've managed to store the data into some objects that are in an array and then iterate through them creating the labels.. something like this:
for (BBItemAttributes *attribute in self.item.productAttributes){
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 50, 10)];
label.text = attribute.displayTemplate;
[self.scrollView addSubview:label];
}
Obviously the problem here is due to creating the UILabels in code and having each one a hard coded CGRect size they are all onto of each other and sometimes don't fit in their respective boxes due to text being too long.
I need a way to line the labels up all on the same X axis point and on different Y axis points, so that they sit next to each other a certain space apart.
Is there a better way to do this?
You need to do something like this;
CGFloat yOrigin = 100;
CGFloat fixedSpace = 10;
for (BBItemAttributes *attribute in self.item.productAttributes)
{
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(100, yOrigin, 50, 10)];
label.text = attribute.displayTemplate;
label.numberOfLines = 0;
[label sizeToFit]; // Resizes label to fit the text.
[self.scrollView addSubview:label];
yOrigin += label.frame.size.height + fixedSpace;
}
Try this. it will help you.
float yAxis = 0;
for (int i = 0; i< 50; i++)//for (BBItemAttributes *attribute in self.item.productAttributes){
{
CGSize size;
UIFont *font = [UIFont systemFontOfSize:15.0]; // Set Your Font
//Your String = attribute.displayTemplate
if (ios7)//Condition to check if ios7
{
//iOS 7
CGRect frame = [#"Your String" boundingRectWithSize:CGSizeMake(50, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
size = CGSizeMake(frame.size.width, frame.size.height+1);
}
else
{
//iOS 6.0
size = [#"Your String" sizeWithFont:font constrainedToSize:CGSizeMake(50, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
}
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(100, yAxis, 50, size.height)];
label.text = #"Your String";//attribute.displayTemplate
label.numberOfLines = 0;
label.tag = i; // Set tag if you want to access in future. :)
[self.scrollView addSubview:label];
// Increase yAxis
yAxis = yAxis + size.height + 10;//10 is extra space if you want between two label
}
// Do Not forget to set Contentsize of your ScrollView.
self.scrollView.contentSize = CGSizeMake(320, yAxis + 20);
If your showing a data structure that is a like a list of labels, I would suggest that you use UITableViewController for showing the list.It has the built in facility and properties that make it easy to display a list of objects.
Now the answer to your first Question.You can get the number of labels by determining the number of objects that are in your array. Something like this :
NSInteger *noOfLabels = yourArray.count;
As far as the length of the text is concerned, I suggest not keeping it very lengthy because Labels are not good for lengthy texts. You can however, specify the number of a lines for a particular label in case if it has lengthy text.This will make the text appear in two lines. Though you will have to adjust width and height accordingly.
You can get the text length by doing something similar to this :
NSString *text;
NSInteger *i = (NSInteger*)[text length];
Hope this helps.

UIButton cannot be displayed

in my app i'm using a scroll View (paging). each view in the scroll view (UIImageView) contains an image and each image has tags (buttons) scattered all over the pic. so here is my code:
for (int i = 0; i < self.pictures.count; i++)
{
//The first loop is to loop to every picture
int nbOfTags = classObject.tagsImages.count;
for (int j = 0; j < nbOfTags; j++)
{
//Second loop is to loop to each tag corresponding to the picture
ListTags *listTags = [[ListTags alloc]init];
NSMutableArray *tagInfo = [[NSMutableArray alloc]init];
listTags = [tagInfo objectAtIndex:j];
float tagX = [listTags.tag_x floatValue];
float tagY = [listTags.tag_y floatValue];
float x = 1024*i+ tagX;
float y = tagY;
CGRect rect = CGRectMake(x, tagY, 20, 20);
UIButton *button = [[UIButton alloc] initWithFrame:rect];
UIImage * buttonImage = [UIImage imageNamed:#"blueCircle.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.scrollView addSubview:button];
}
}
problem: when i run the code i can't see the buttons (tags) on the picture. if i replace "i" with "j" in
float x = 1024*i+ tagX;
the buttons can be seen, however it's not the desired coordinates. so why "i" can't work? am i doing anything wrong or missing anything?
In interface builder (or storyboard - IB) uncheck autolayout (if it's checked) then your button will be displayed where you want.
See my comments in the code below:
for (int i = 0; i < self.pictures.count; i++)
{
//The first loop is to loop to every picture
/*
* This will give you the same number of tags for every image.
* Is that what you want?
*/
int nbOfTags = classObject.tagsImages.count;
for (int j = 0; j < nbOfTags; j++)
{
//Second loop is to loop to each tag corresponding to the picture
/* This allocates a brand new ListTags object EVERY time through the loop. */
ListTags *listTags = [[ListTags alloc]init];
/* This allocates a brand new EMPTY array EVERY time through the loop. */
NSMutableArray *tagInfo = [[NSMutableArray alloc]init];
/*
* This discards the new ListTags object that you just created two lines ago
* and replaces it with an object from tagInfo. Which doesn't exist because
* you just created a new array in the previous line. This really should
* crash, which leads me to believe that this isn't the actual code that you
* are using. Post the actual code that you are using so that we can help you
* better.
*/
listTags = [tagInfo objectAtIndex:j];
/* None of this is valid since listTags is nil/we never should have gotten here. */
float tagX = [listTags.tag_x floatValue];
float tagY = [listTags.tag_y floatValue];
float x = 1024*i+ tagX;
float y = tagY;
CGRect rect = CGRectMake(x, tagY, 20, 20);
UIButton *button = [[UIButton alloc] initWithFrame:rect];
UIImage * buttonImage = [UIImage imageNamed:#"blueCircle.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.scrollView addSubview:button];
}
}

Initializing words of a sentence stored in a string into UILabels

I am trying to initialise the words of a sentence into UIlabels in the order of the word of the sentence every time I click on a UIbutton.
I also want to recognise when the sentence in the different labels is approaching the end of the screen, which then takes the next word and puts it in the line below the words of the sentence like pressing Enter in Microsoft Word.
I have tried this code but it loads all the words on the same spot.
- (void)change:(id)sender
{
NSString *sentence = #"i am a boy with passion";
NSArray *array = [sentence componentsSeparatedByCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString:#" "]];
CGFloat xVal = 11.0;
for (NSString *words in array) {
UILabel *labelText = [[UILabel alloc]initWithFrame:CGRectMake(xVal, 50, 300, 80)];
labelText.layer.borderColor = [UIColor blueColor].CGColor;
labelText.layer.borderWidth = 6.0;
labelText.backgroundColor = [UIColor clearColor];
labelText.textColor = [UIColor blackColor];
labelText.font = [UIFont boldSystemFontOfSize:20.0f];
labelText.text = words;
xVal=+200;
[self.view addSubview:labelText];
[labelText setUserInteractionEnabled:YES];
[labelText sizeToFit];
xVal=+200; means xVal=200. So except first label all others got same origin. Thats why they got over lapped.
For finding whether the label moved out of bounds
Initialise yVal outside for loop,
Inside the loop add
CGFloat width = [words sizeWithFont:[UIFont systemFontOfSize:[UIFont systemFontSize]]].width;
if (self.view.frame.size.width<xVal+width) {
yVal+=50;
xVal = 11;
}
UILabel *labelText = [[UILabel alloc]initWithFrame:CGRectMake(xVal, yVal, 300, 80)];
Make sure to use, a)the font you would be using for label in finding the width, b) adjust increment in yVal according to yor need.
Dont forget to change xVal=+200; to xVal+=200;
Your problem is this line:
xVal=+200;
This is the same as saying xVal = 200; the plus sign means positive 200 rather than 200 more. Try this instead:
xVal += 200;

How to add UIView to UIScrollView dynamically if previous UIView is full

I have to do a pdf generator with custom label, so in my storyboard I have a UIScrollView with a UIView inside it, and if my UIView is full, I want to add another UIView and fill it with other label that is not already in. How can I add another page in my UIScrollView with another UIView ? I have to do it programmatically or there is an option in storyboard for doing it ?
I tried this (I don't know if it works and I don't want to compile it 'cause I find it really really ugly) :
CGFloat placement = titleLabel.frame.size.height + kMarginLabel;
for(int i = 0; i < [contract.nameContract count]; i++)
{
if(placement > _contractPageView.frame.size.height)
{
CGFloat secondPlacement = 0;
_scrollView.contentSize = CGSizeMake(_contractPageView.frame.size.width * 2, _contractPageView.frame.size.height);
UIView *secondPage = [[UIView alloc] initWithFrame:_contractPageView.frame];
articleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0 + kMarginLabel, secondPlacement, kTitleHeight, kTitleWidth)];
articleLabel.text = [NSString stringWithFormat:#"Article %i - %#",i, [contract.nameContract objectAtIndex:i]];
[secondPage addSubview:articleLabel];
secondPlacement += articleLabel.frame.size.height;
clauseLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, secondPlacement + kMarginLabel, _contractPageView.frame.size.width, kSizeOfClause)];
clauseLabel.text = [contract.textContract objectAtIndex:i];
secondPlacement += clauseLabel.frame.size.height;
[secondPage addSubview:clauseLabel];
[_scrollView addSubview:secondPage];
if(secondPlacement > secondPage.frame.size.height)
{
CGFloat thirdPlacement = 0;
_scrollView.contentSize = CGSizeMake(_contractPageView.frame.size.width * 3, _contractPageView.frame.size.height);
UIView *thirdPage = [[UIView alloc] initWithFrame:_contractPageView.frame];
articleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0 + kMarginLabel, thirdPlacement, kTitleHeight, kTitleWidth)];
articleLabel.text = [NSString stringWithFormat:#"Article %i - %#",i, [contract.nameContract objectAtIndex:i]];
[thirdPage addSubview:articleLabel];
thirdPlacement += articleLabel.frame.size.height;
clauseLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, thirdPlacement + kMarginLabel, _contractPageView.frame.size.width, kSizeOfClause)];
clauseLabel.text = [contract.textContract objectAtIndex:i];
thirdPlacement += clauseLabel.frame.size.height;
[thirdPage addSubview:clauseLabel];
[_scrollView addSubview:thirdPage];
}
} else {
articleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, placement, kTitleHeight, kTitleWidth)];
articleLabel.text = [NSString stringWithFormat:#"Article %i - %#",i, [contract.nameContract objectAtIndex:i]];
[_contractPageView addSubview:articleLabel];
placement += articleLabel.frame.size.height;
clauseLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, placement + kMarginLabel, _contractPageView.frame.size.width, kSizeOfClause)];
clauseLabel.text = [contract.textContract objectAtIndex:i];
placement += clauseLabel.frame.size.height;
[_contractPageView addSubview:clauseLabel];
}
}
I don't know if it's the only method, and imagine if I have many and many many many object in my array, I have to create more and more page :/ I don't know how to do it :(
Thanks for your help.
I did some similar code for a generic core data editor for one of our projects. So as I see it you got two options:
Use a collection view design the prototype view as your page and hook it up to an array controller that manages your text. The text could be organised as an array of NSAttributedString that you could bind to a NSTextView (one for each page)
If you need more flexibility, i.e. pages of different sizes, different layouts etc.., you could program your own container that keep as properties an array of "Pages" (you would need to define this class) and whenever this array is changed recomputes the sizes and constraints by, for example by adding up the heights of every pages and sizing your content view appropriately.
Hope it helps

Resources