So, I have the slider adding UITextFields but it's not updating/subtracting UITextField's when selecting less than the previous Slider Value. Does [self.view addSubview:textField]; need to be outside of the for loop? Thanks in advance.
- (IBAction) sliderValueChanged:(UISlider *)sender {
float senderValue = [sender value];
int roundedValue = senderValue * 1;
ingredientLabel.text = [NSString stringWithFormat:#"%d", roundedValue];
int moveYBy = 35;
int baseY = 140;
for(int y = 0; y < roundedValue; y++){
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, baseY, 227, 31)];
textField.text = [NSString stringWithFormat:#"%d", roundedValue];
textField.borderStyle = UITextBorderStyleRoundedRect;
baseY = baseY + moveYBy;
[self.view addSubview:textField];
[textField release];
NSLog(#"Adding %d fields!", roundedValue);
}
NSLog(#"%d", roundedValue);
}
You are creating N text fields everytime the slider value changes (where n is the rounded value).
Instead, you should make an NSMutableArray an iVar and store all the text fields there, when roundedValue is bigger than the number of text fields in that array, we add more. When it's smaller, we remove some.
(I'm using an iVar called textFieldsArray, and I also changed a little the way the y is calculated for the arrays)
- (IBAction) sliderValueChanged:(UISlider *)sender {
float senderValue = [sender value];
int roundedValue = senderValue * 1;
ingredientLabel.text = [NSString stringWithFormat:#"%d", roundedValue];
for(int y = 0; y < roundedValue; y++){
if(y > [textFieldsArray count]){
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 140 + 35 * y, 227, 31)];
textField.text = [NSString stringWithFormat:#"%d", roundedValue];
textField.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:textField];
[textFieldsArray addObject:textField];
[textField release];
NSLog(#"Adding %d fields!", roundedValue);
}
}
while([textFieldsArray count] > roundedValue){
UITextField *textField = [textFieldsArray lastObject];
[textField removeFromSuperview];
[textFieldsArray removeLastObject];
}
NSLog(#"%d", roundedValue);
}
Related
I am looking for a function or a loop prototype to add UILabels to a view on iPhone. The reason for this is I won't know in advance how many labels I need to add, so they will need to be added dynamically.
My pseudo code is as follows. The idea is that each label is given a string and then placed in the next screen, hence the +self.view.frame.size.width statement. Paging etc work perfectly, the problem is all the labels appear to be ending up on the second screen i.e. Label 3 appears on top of label 2. The issue would appear to be I am always referencing altLabel, and as such once I move to the second position, I am constantly referencing that position and never moving once there.
I can use the 'count' variable to multiple the screen width, but if I do that, every time I update the label text, it will overwrite the previous.
int count = 0;
int maxNumber = 10;
while(count < maxNumber) {
//Add a label
UILabel *altlabel; //Declare the label
if (count > 0) {
//Move the label
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(altlabel.frame)+self.view.frame.size.width,10,300,25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class+count];
}
else {
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(10,10,300,25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class];
}
altlabel.textColor = [UIColor greenColor];
[altlabel sizeToFit];
[_scrollView addSubview:altlabel];
count++;
}
The problem is this line:
UILabel *altlabel; // Declare the label
if (count > 0) {
//Move the label
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(altlabel.frame)+self.view.frame.size.width,10,300,25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class+count];
}
You are setting up the frame using altlabel.frame, but there altlabel is not setted up: you redeclared it on the first line with UILabel *altlabel.
With this code every label but the first will have the same frame. Try with this:
int count = 0;
int maxNumber = 10;
CGRect rect;
while(count < maxNumber) {
// Add a label
UILabel *altlabel; // Declare the label
if (count > 0) {
//Move the label
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(rect.frame)+self.view.frame.size.width*count, 10, 300, 25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class+count];
} else {
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class];
}
rect = altlabel.frame;
altlabel.textColor = [UIColor greenColor];
[altlabel sizeToFit];
[_scrollView addSubview:altlabel];
count++;
}
Now the frame of new label is saved in a temporary var (CGRect frame) and you can use it.
This code should work:
int count = 0;
int maxNumber = 10;
while(count < maxNumber) {
//Add a label
UILabel *altlabel; //Declare the label
if (count > 0) {
//Move the label
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(altlabel.frame)+(self.view.frame.size.width*count),10,300,25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class+count];
}
else {
altlabel = [[UILabel alloc] initWithFrame:CGRectMake(10,10,300,25)];
altlabel.text = [NSString stringWithFormat:#"%# %# (%d)", _name,_age, class];
}
altlabel.textColor = [UIColor greenColor];
[altlabel sizeToFit];
[_scrollView addSubview:altlabel];
count++;
}
A much cleaner approach would be to predetermine the frame of your label before creation and then add it as a subview (or perhaps save each label to an array for reference later on).
NSInteger numberOfLabels = 10;
CGFloat labelHeight = 25.0;
CGFloat padding = 10.0;
for(NSInteger index = 0; index < numberOfLabels; ++index)
{
CGRect frame = CGRectMake(10.0, (index * (labelHeight + padding)), 300.0, labelHeight);
UILabel *label = [[UILabel alloc] initWithFrame:frame];
[[self view] addSubview:label];
}
You may want to assign the label a tag with setTag: to reference each label, or gather then from an array rather than looping through subviews to gather or append text after they have been created.
I think the problem will be that your label 'altLabel' is being reinitialised each time the loop runs through and therefore the frame of the label is also being reset.
This means that every time a new label is created, the frame will be in exactly the same place.
A simple way to fix this would simply be to move the initial declaration of the label to outside the while loop.
A potentially better and more efficient fix would require a rework of the loop used. When I do things like this, I tend to use a for loop as you have use of an index to help position things:
for(int i = 0; i < 10; i++)
{
//Getting the x-position correct here may take a little trial and error
UILabel *altLabel = [[UILabel alloc] initWithFrame:CGRectMake(INSET + i*LABEL_WIDTH, 10, 300, 25)];
[altLabel setText:[NSString stringWithFormat:#"%# %# (%d)", _name,_age, class+count]];
[altLabel setTextColor:[UIColor greenColor]];
[altLabel sizeToFit];
[_scrollView addSubview:altLabel];
}
This should then mean you don't need a counter.
Hopefully this helps!
Matt
I am creating labels dynamically from NSMutableArray.While creating labels I have set tags for each label. I have one NSMutableArray named wordArray. Now, I want to check my string is available in wordArray or not,
I can check this using :
[wordArray containsObject:wordStr];
For creating labels dynamically :
UILabel *wordLabl;
int tagValue3 = 1;
for (int iloop = 0; iloop < [wordArray count]; iloop++)
{
wordLabl = [self addwordLabelRect:CGRectMake(80 * iloop + 20, 420 , 100, 20)andTag:tagValue3];//30 + 35 30 * iloop+
[self.view addSubview:wordLabl];
tagValue3 += 1;
}
-(UILabel *)addwordLabelRect:(CGRect)rect andTag:(int)integerValue
{
wordLabel = [[UILabel alloc] init];
wordLabel.frame = rect;
wordLabel.userInteractionEnabled = YES;
wordLabel.tag = integerValue;
wordLabel.backgroundColor = [UIColor clearColor];
wordLabel.font = [UIFont systemFontOfSize:15];
wordLabel.text = [NSString stringWithFormat:#"%#",[wordArray objectAtIndex:integerValue - 1]];
wordLabel.textAlignment = NSTextAlignmentCenter;
wordLabel.textColor = [UIColor whiteColor];
return wordLabel;
}
Using above code I am creating labels and Tags.
But,If wordArray contains the string I want to change the textColor of that label.I think this can be done using Tag , but how can I get the tag value of the label.
Sorry, I overlooked you code... You just need to add following lines where you want to access your appropriate label:
if([wordArray containsObject:wordStr])
{
UILabel *label = (UILabel *) [self.view viewWithTag:([wordArray indexOfObject:wordStr] - 1)];//since u started tag assignment from 1
label.textcolor = [UIColor yellowColor];
}
I guess you're doing something like that to set the tags ?
for (NSUInteger i = 0; i < [wordArray count]; ++i) {
UILabel * label;
// setup your label...
[label setTag:i];
[yourView addSubview:label];
}
If so, just do :
NSUInteger index = [wordArray indexOfObject:wordStr];
if (index != NSNotFound) {
UILabel * label = [yourView viewWithTag:index];
// do whatever you want with your label
}
Good luck.
if you want to get UILabel from its Tag.
you can use following loop
int i=0;
for (NSObject *view in self.View.subviews)
{
if ([view isKindOfClass:[UILabel class]])
{
label = (UILabel *)[[self view] viewWithTag:wordArray[i]];
NSLog(#"%#",label.text);
//here you get your label
}
i++;
}
I have a UITextView which display a paragraph. For example:
self.myTextView.text = #"This is a sample paragraph"
What I want to do now is when I touch up a word in this paragraph, such as "This", a function will be call: [self aFunction:#"This"]
Are there any ideas for handling this event and the way to get the parameter, which is the word user touched. Maybe, I need other way to display the paragraph, not by a UITextView.
In following example use (UITextView)
I created a simple UILabel subclass that allows me to set the inset value:
#import "WWLabel.h"
#define WWLabelDefaultInset 5
#implementation WWLabel
#synthesize topInset, leftInset, bottomInset, rightInset;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.topInset = WWLabelDefaultInset;
self.bottomInset = WWLabelDefaultInset;
self.rightInset = WWLabelDefaultInset;
self.leftInset = WWLabelDefaultInset;
}
return self;
}
- (void)drawTextInRect:(CGRect)rect
{
UIEdgeInsets insets = {self.topInset, self.leftInset,
self.bottomInset, self.rightInset};
return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
Then I created a UIView subclass that contained my custom label, and on tap constructed the size of the text for each word in the label, until the size exceeded that of the tap location - this is the word that was tapped. It's not prefect, but works well enough for now.
I then used a simple NSAttributedString to highlight the text:
#import "WWPhoneticTextView.h"
#import "WWLabel.h"
#define WWPhoneticTextViewInset 5
#define WWPhoneticTextViewDefaultColor [UIColor blackColor]
#define WWPhoneticTextViewHighlightColor [UIColor yellowColor]
#define UILabelMagicTopMargin 5
#define UILabelMagicLeftMargin -5
#implementation WWPhoneticTextView {
WWLabel *label;
NSMutableAttributedString *labelText;
NSRange tappedRange;
}
// ... skipped init methods, very simple, just call through to configureView
- (void)configureView
{
if(!label) {
tappedRange.location = NSNotFound;
tappedRange.length = 0;
label = [[WWLabel alloc] initWithFrame:[self bounds]];
[label setLineBreakMode:NSLineBreakByWordWrapping];
[label setNumberOfLines:0];
[label setBackgroundColor:[UIColor clearColor]];
[label setTopInset:WWPhoneticTextViewInset];
[label setLeftInset:WWPhoneticTextViewInset];
[label setBottomInset:WWPhoneticTextViewInset];
[label setRightInset:WWPhoneticTextViewInset];
[self addSubview:label];
}
// Setup tap handling
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleTap:)];
singleFingerTap.numberOfTapsRequired = 1;
[self addGestureRecognizer:singleFingerTap];
}
- (void)setText:(NSString *)text
{
labelText = [[NSMutableAttributedString alloc] initWithString:text];
[label setAttributedText:labelText];
}
- (void)handleSingleTap:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
// Get the location of the tap, and normalise for the text view (no margins)
CGPoint tapPoint = [sender locationInView:sender.view];
tapPoint.x = tapPoint.x - WWPhoneticTextViewInset - UILabelMagicLeftMargin;
tapPoint.y = tapPoint.y - WWPhoneticTextViewInset - UILabelMagicTopMargin;
// Iterate over each word, and check if the word contains the tap point in the correct line
__block NSString *partialString = #"";
__block NSString *lineString = #"";
__block int currentLineHeight = label.font.pointSize;
[label.text enumerateSubstringsInRange:NSMakeRange(0, [label.text length]) options:NSStringEnumerationByWords usingBlock:^(NSString* word, NSRange wordRange, NSRange enclosingRange, BOOL* stop){
CGSize sizeForText = CGSizeMake(label.frame.size.width-2*WWPhoneticTextViewInset, label.frame.size.height-2*WWPhoneticTextViewInset);
partialString = [NSString stringWithFormat:#"%# %#", partialString, word];
// Find the size of the partial string, and stop if we've hit the word
CGSize partialStringSize = [partialString sizeWithFont:label.font constrainedToSize:sizeForText lineBreakMode:label.lineBreakMode];
if (partialStringSize.height > currentLineHeight) {
// Text wrapped to new line
currentLineHeight = partialStringSize.height;
lineString = #"";
}
lineString = [NSString stringWithFormat:#"%# %#", lineString, word];
CGSize lineStringSize = [lineString sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode];
lineStringSize.width = lineStringSize.width + WWPhoneticTextViewInset;
if (tapPoint.x < lineStringSize.width && tapPoint.y > (partialStringSize.height-label.font.pointSize) && tapPoint.y < partialStringSize.height) {
NSLog(#"Tapped word %#", word);
if (tappedRange.location != NSNotFound) {
[labelText addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:tappedRange];
}
tappedRange = wordRange;
[labelText addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:tappedRange];
[label setAttributedText:labelText];
*stop = YES;
}
}];
}
}
I have three UIButtons which display in a random order using:
NSMutableArray *indexArray = [NSMutableArray arrayWithObjects:
[NSValue valueWithCGRect:CGRectMake(20, 187, 280, 44)],
[NSValue valueWithCGRect:CGRectMake(20, 258, 280, 44)],
[NSValue valueWithCGRect:CGRectMake(20, 330, 280, 44)], nil];
//Randomize the array
NSUInteger count = [indexArray count];
for (NSUInteger i = 0; i < count; ++i) {
int nElements = count - i;
int n = (arc4random() % nElements) + i;
[indexArray exchangeObjectAtIndex:i withObjectAtIndex:n];
}
//Assign the frames
button1.frame = [((NSValue *)[indexArray objectAtIndex:0]) CGRectValue];
button2.frame = [((NSValue *)[indexArray objectAtIndex:1]) CGRectValue];
button3.frame = [((NSValue *)[indexArray objectAtIndex:2]) CGRectValue];
For some reason I an unable to hide these buttons after they display a number of items. I have tried for example
button1.hidden = YES; and also
[self.button1.hidden = YES];
Any ideas? Any help would be most appreciated.
Jamie
Pass tag to Buttons and use below code
for (UIButton *btn in [self.view subviews])
{
if (btn.tag==1)
{
[btn removeFromSuperview];
}
}
and your problem will be resolved and revert me..
These buttons are IBOUTLET?
You can think of another way to hide
like, '[UIView viewWithTag:(NSInteger)]
sample code is here
UIButton *tmpBtn = (UIButton *)[self.view viewWithTag:1]; // tag is your choice
tmpBtn.hidden = YES
To do this I use this:
if ([questions count]== 11)
{ button1.hidden = YES; button2.hidden = YES; button3.hidden = YES }
I would suggest you check two things:
that you effectively take the branch;
that your button* variables are not nil.
e.g.:
if ([questions count]== 11)
{
NSLog(#"Enter branch with %x, %x, %x", button1, button2, button3);
button1.hidden = YES; button2.hidden = YES; button3.hidden = YES;
}
(ignore the warning that you will get on NSLog).
I'm trying to create a simple pickerview with two components, drawing its label data from a small mutablearray and output data from a simple matrix. The purpose of this wheel is to select a value from 0 to 1000, and then spit out the number in a label and the value to the rest of the application's functions.
Some specific info about what I'm doing: (skip down to the last paragraph for the problem)
The left wheel spins a "hundred's" column, and the right wheel spins a "ten's" column, so essentially you're creating one value from two wheels. All I want to do is let the user create a value of 0, 10, 20, 30... 990, 1000 (every ten units up to 1000).The first component is easy to label, but I have two arrays to populate the second component's row's labels. The first array for the second component creates the 00 - 90 label, the second array (for when 1000 is selected) just has a 00 value. So when the user wants to select 1000, the 10 is on the first wheel and 00 on the second. I change the row count for the second wheel component when the first wheel component is at row 10. So now the second component only shows "00". My didSelectRow method uses a matrix for values of 0 - 990 and works great. And I just make a string and convert it to a number for when the user selects 1000 using if statements.
The problem is in the rare circumstance of when the user spins Component 0 to create the value of "1000" (the last row), and if they were start spinning the second component before the first component has a chance to stop spinning (basically spinning in a hurry!), the app crashes. I think it's trying to find a value for a row that doesn't exist. I have other parts of my app that function similarly and they also crash under the same situation. Is there a problem with my approach to changing the number of rows/labels for rows based on the selection of a different component? Or is it something simple in my code?
Thanks for reading and thanks in advance for any help!
Here's the code:
//Baggage Array
baggageHundredsArray = [[NSMutableArray alloc] init];
for (int i = 1; i <= 10; i++) {
NSString *myBagString = [NSString stringWithFormat:#"%d", i];
[baggageHundredsArray addObject:myBagString];
}
[baggageHundredsArray insertObject:#"- " atIndex:0];
baggageTensArray = [[NSMutableArray alloc] init];
for (int i = 10; i <= 90; i = i + 10) {
NSString *myBagString2 = [NSString stringWithFormat:#"%d lbs.", i];
[baggageTensArray addObject:myBagString2];
}
[baggageTensArray insertObject:#"00 lbs." atIndex:0];
baggageTensArray2 = [[NSMutableArray alloc] init];
[baggageTensArray2 insertObject:#"00 lbs." atIndex:0];
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
if (thePickerView == baggagePicker) {
NSInteger numComps2 = 0;
switch (component)
{
case 0:
numComps2 = [baggageHundredsArray count];
break;
case 1:
if ([baggagePicker selectedRowInComponent:0] <= 9)
{
numComps2 = [baggageTensArray count];
}
else
{
numComps2 = [baggageTensArray2 count];
}
break;
}
return numComps2;
}
}
- (UIView *)pickerView:(UIPickerView *)pickerView
viewForRow:(NSInteger)row
forComponent:(NSInteger)component
reusingView:(UIView *)view {
UILabel *pickerLabel = (UILabel *)view;
if (pickerView == baggagePicker) {
if ((pickerLabel == nil) || ([pickerLabel class] != [UILabel class])) { //newlabel
CGRect frame = CGRectMake(0.0, 0.0, 110, 32.0);
pickerLabel = [[[UILabel alloc] initWithFrame:frame] autorelease];
pickerLabel.textAlignment = UITextAlignmentLeft;
pickerLabel.backgroundColor = [UIColor clearColor];
pickerLabel.font = [UIFont boldSystemFontOfSize:12];
}
pickerLabel.textColor = [UIColor blackColor];
switch (component)
{
case 0:
//CGRect frame = CGRectMake(0.0, 0.0, 80, 32);
//pickerLabel = [[[UILabel alloc] initWithFrame:frame] autorelease];
[pickerLabel setTextAlignment:UITextAlignmentRight];
[pickerLabel setBackgroundColor:[UIColor clearColor]];
[pickerLabel setFont:[UIFont boldSystemFontOfSize:23]];
[pickerLabel setTextColor:[UIColor blackColor]];
[pickerLabel setText:[baggageHundredsArray objectAtIndex:row]];
break;
case 1:
if ([baggagePicker selectedRowInComponent:0] <= 9) {
[pickerLabel setTextAlignment:UITextAlignmentLeft];
[pickerLabel setBackgroundColor:[UIColor clearColor]];
[pickerLabel setFont:[UIFont boldSystemFontOfSize:21]];
[pickerLabel setTextColor:[UIColor blackColor]];
[pickerLabel setText:[baggageTensArray objectAtIndex:row]];
}
else
{
[pickerLabel setTextAlignment:UITextAlignmentLeft];
[pickerLabel setBackgroundColor:[UIColor clearColor]];
[pickerLabel setFont:[UIFont boldSystemFontOfSize:21]];
[pickerLabel setTextColor:[UIColor blackColor]];
[pickerLabel setText:[baggageTensArray2 objectAtIndex:row]];
}
break; }
return pickerLabel;
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (thePickerView == baggagePicker) {
[baggagePicker reloadAllComponents];
NSInteger hundredsWheel = [thePickerView selectedRowInComponent:0];
NSInteger tensWheel = [thePickerView selectedRowInComponent:1];
//lbs.
int column5 [10][10] = {
{0,10,20,30,40,50,60,70,80,90},
{100,110,120,130,140,150,160,170,180,190},
{200,210,220,230,240,250,260,270,280,290},
{300,310,320,330,340,350,360,370,380,390},
{400,410,420,430,440,450,460,470,480,490},
{500,510,520,530,540,550,560,570,580,590},
{600,610,620,630,640,650,660,670,680,690},
{700,710,720,730,740,750,760,770,780,790},
{800,810,820,830,840,850,860,870,880,890},
{900,910,920,930,940,950,960,970,980,990},
};
// Totals Label
if (hundredsWheel <= 9) {
myBaggageString = [NSString stringWithFormat:#"%i", (column5[hundredsWheel][tensWheel])];
baggageWeightLabel.text = myBaggageString;
baggageWeightInt = [myBaggageString intValue];
baggageWeightFloat = [myBaggageString floatValue];
baggageMomentFloat = baggageWeightFloat * 731.10;
[self calculateWeight];
paxViewBaggageWeightLabel.text = myBaggageString;
NSLog(#"value of myBaggageString is %#", myBaggageString);
[baggagePicker reloadAllComponents];
}
if (hundredsWheel == 10){
myBaggageString = [NSString stringWithFormat:#"1000"];//, [lastFuelValues objectAtIndex: [weightPicker selectedRowInComponent:1]]];
baggageWeightLabel.text = myBaggageString;
baggageWeightInt = [myBaggageString intValue];
baggageWeightFloat = [myBaggageString floatValue];
baggageMomentFloat = baggageWeightFloat * 731.10;
[self calculateWeight];
paxViewBaggageWeightLabel.text = myBaggageString;
[baggagePicker reloadAllComponents];
}