I am refactoring an 'old' Objective-C iOS-program. All layout is done programmatically without storyboard.
I am experiencing some odd behavior when I try to update the text on a UILabel. The text is NOT updated but written 'on top' of the existing text.
The context is:
The UILabel is defined in a 'top-bar' that is managed by a sub-ViewController. It is assigned as 'default'/placeholder value when initialized by the sub-ViewController.
lblArea = [[UILabel alloc] initWithFrame:CGRectMake(x, y, width, height)];
//self.lblArea.text = #"giraf";
lblArea.textColor = BLACK_COLOR;
lblArea.backgroundColor = [UIColor clearColor];
lblArea.textAlignment = NSTextAlignmentCenter;
lblArea.font = [UIFont fontWithName:#"HelveticaNeue-Medium" size:14];
//self.lblArea.text=SEARCH_FOR_ADDRESS;
NSAttributedString *placeholderText = [[NSMutableAttributedString alloc] initWithString:SEARCH_FOR_ADDRESS attributes : #{
NSForegroundColorAttributeName : GRAY_COLOR,
}];
lblArea.attributedText=placeholderText;
[self.view addSubview:lblArea];
The setter-method is
-(void)setLabelAreaText:(NSString *)labelText{
lblArea.text=labelText;
}
In the parent controller the sub-controller is added as follows:
[self addChildViewController:topBarViewController];
[topBarViewController didMoveToParentViewController:self];
[self.view addSubview:[topBarViewController view]];
When the label is assigned another value from the parent-ViewController (via a setter method) the text is not replaced but written 'on top' of the existing.
The UILabel is defined as a instance variable and is made accesiable via a custom setter-method. I have tried to change it to a public property but it doesn't change anything.
Can anyone please help with an explanation :-)
Related
I have an UIViewController in which I create an UILabel programmatically in its' viewDidLoad: like so:
- (void)viewDidLoad
{
UILabel *navTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(17, 0, 100, 100)];
navTitleLabel.backgroundColor = [UIColor clearColor];
navTitleLabel.textAlignment = NSTextAlignmentCenter;
navTitleLabel.textColor=[UIColor colorWithHexString:#"#000029"];
[navTitleLabel setFont:[UIFont fontWithName:#"Pennyscript" size:20]];
self.navigationItem.titleView = navTitleLabel;
}
I have the "User defined Runtime Attribute" set in the ViewController's identity inspector tab:
What I'm trying to do here is programmatically set the UILabel navTitleLabel's font to my custom font, then add that UILabel into the navigationBar's titleView. What am I doing wrong? How can I accomplish this goal?
With the UDKA(User defined key attribute) in the VC ID-inspector, the app crashes with this stack trace message:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key fontName.'
When I remove my User Defined Key Attribute from the ViewController, I can then navigate to the VC with no crash.
In your View Controller define a property as:
#property (nonatomic, copy) NSString *myFontName;
And in the view controllers Identity inspector change the Keypath from fontName to myFontName.
And change this code:
[navTitleLabel setFont:[UIFont fontWithName:#"Pennyscript" size:20]];
to:
[navTitleLabel setFont:[UIFont fontWithName:myFontName size:20]];
Tutorials:
Reference
Reference
Reference
Reference
The exception that you get is because you try to set a property (this is what setValue:forKeypath: is doing) of UILabel. Since you pass the string fontName as keypath, iOS attempts to set the property fontName of UILabel to the value NavBar Title. This is why you are getting the exception, because UILabel doesn't have a property called fontName! Calling [label setFont:[UIFont fontWithName:#"Pennyscript" size:20]]; should be enough!
Copy font in project File. add in project then add in info.plist
then put this methods
UILabel *navTitleLabel = [[UILabel alloc]
initWithFrame:CGRectMake(17, 0, 100, 100)];
navTitleLabel.backgroundColor = [UIColor clearColor];
navTitleLabel.textAlignment = NSTextAlignmentCenter;
navTitleLabel.text = #"hello";
navTitleLabel.font = [UIFont fontWithName:#"Pennyscript" size:navTitleLabel.font.pointSize];
self.navigationItem.titleView = navTitleLabel;
When I set the custom font for the segmented control then it changes the vertical text alignment. I am using below code to set the font .
// I dont think these lines are creating any issue but just wanted to paste all the code
self.segmentType.layer.borderColor = navigationTintColor.CGColor;
self.segmentType.layer.cornerRadius = 0.0;
self.segmentType.layer.borderWidth = 1.5;
// These are the lines that are changing the text alignment
UIFont *font = [UIFont fontWithName:ftHelveticaNeueLTPro_Th size:13.5];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font
forKey:UITextAttributeFont];
[self.segmentType setTitleTextAttributes:attributes
forState:UIControlStateNormal];
Here is the screenshot of whats is happening . If you observer, the text is not vertically centre aligned .
Please help me . Thank you in advance !!
The below code suggested by #Emmanuel works perfectly fine. You can change the vertical offset to align the text vertically at the center .
[self.segmentType setContentPositionAdjustment:UIOffsetMake(0, 2) forSegmentType:UISegmentedControlSegmentAny barMetrics:UIBarMetricsDefault];
Can you please try it using custom UILabel on custom view on it. Change & modify frame value of either titleLabel or customSegmentView as per convenience on actual view. And add this whole view as subview on your segmented control.
UIView *customSegmentView = [[UIView alloc] init];
UILabel *segmentTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 7.0f,180.0f,22.6f)];
segmentTitleLabel.text = #"your-text";
segmentTitleLabel.backgroundColor = [UIColor clearColor];
segmentTitleLabel.textAlignment = UITextAlignmentCenter;
segmentTitleLabel.font = [UIFont fontWithName:#"ftHelveticaNeueLTPro_Th" size:13.5f];
customSegmentView.frame = CGRectMake(60, 20, 180, 35);
[customSegmentView addSubview:segmentTitleLabel];
[self.segmentType setTitleView:customSegmentView];
Hope that will work for your issue. Please check and let me know if we have to go with another solution.
In InterfaceBuilder on XCode 6 there is a Content Offset control for the segments, which affects the baseline of the text. I had this problem because my Content Offset was 2 in the Y dimension instead of 0.
I created a UITextField programatically, (I do not use storyboard) and added it as a subview to ViewController with this code:
#interface ViewController ()
#property (nonatomic, strong) UITextField *searchLocationBar;
#end
...
#synthesize searchLocationBar;
...
self.searchLocationBar = [[UITextField alloc] init];
self.searchLocationBar.frame = CGRectMake(0.0f, 0.0f, 320.0f, 40.0f);
self.searchLocationBar.delegate = self;
self.searchLocationBar.borderStyle = UITextBorderStyleRoundedRect;
self.searchLocationBar.placeholder = #"a temporary placeholder";
self.searchLocationBar.userInteractionEnabled = YES;
self.searchLocationBar.clearButtonMode = UITextFieldViewModeAlways;
[self.view addSubview:self.searchLocationBar];
However, I cannot enter any text - nothing happens, when I tap on a textfield. It's not overlapped by any other view.
I've checked UITextfield not editable-iphone but no effect
I'm newbie and totally sure I simply miss something - please advice.
Thanks!
EDIT:
One more thing: I have a Google Maps GMSMapView assigned to self.view as
self.view = mapView_; as written in Google API documentation.
After some tests I found that with this declaration all controls work perfectly, but not textfields. I would prefer not to move a map view to any subview as I will need to rewrite lots of things.
Can someone please add any suggestions?
you forget add:
[self.view bringSubviewToFront:self.searchLocationBar];
In Xcode 5 your code should work.Better you check your Xcode version.May be the problem with your code with Xcode versions.You can try by following way.
UITextField *lastName = [[[UITextField alloc] initWithFrame:CGRectMake(10, 100, 300, 30)];
[self.view addSubview:lastName];
lastName.placeholder = #"Enter your last name here"; //for place holder
lastName.textAlignment = UITextAlignmentLeft; //for text Alignment
lastName.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:14.0]; // text font
lastName.adjustsFontSizeToFitWidth = YES; //adjust the font size to fit width.
lastName.textColor = [UIColor greenColor]; //text color
lastName.keyboardType = UIKeyboardTypeAlphabet; //keyboard type of ur choice
lastName.returnKeyType = UIReturnKeyDone; //returnKey type for keyboard
lastName.clearButtonMode = UITextFieldViewModeWhileEditing;//for clear button on right side
lastName.delegate = self; //use this when ur using Delegate methods of UITextField
There are lot other attributes available but these are few which we use it frequently.if u wanna know about more attributes and how to use them refer to the following link.
You can also make property for UITextField.Either way should work fine in Xcode.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextField_Class/Reference/UITextField.html
For reasons of reusability, I'm interested in finding a way to programmatically add text and custom UITextFields to a view in an efficient manner, similar to how you can combine strings using NSString's stringWithFormat: and then assign the result to a UILabel's text attribute. Ideally, with 2-3 statements I could write text and include my UITextField Objects in a string, and get an automatically text-wrapped, nicely formatted UIView that I can embed directly into my view. Basically, it would function like a UILabel with the ability to add UIView objects. For an example of the output this image would be a combination of both text and underlined UITextFields:
If this exists, it would allow me to reuse a single UITableViewCell subclass rather than having 5-6 xibs and 3-4 subclasses. I've searched about 2 hours with no real luck for a pre-existing solution, so has anyone ever encountered this problem before and used or released a library to handle this, or is there a simple solution I'm overlooking?
Thank you!
you can use CSLinearLayoutView (https://github.com/scalessec/CSLinearLayoutView)
and create a class
#implementation LabledView
+ (UIView*)create :(CGRect) frame view:(UIView*) view labelTitle:(NSString*)labelTitle viewLinearLayoutMakePadding :(CSLinearLayoutItemPadding)viewLinearLayoutMakePadding labelLinearLayoutMakePadding :(CSLinearLayoutItemPadding)labelLinearLayoutMakePadding font:(UIFont*)font textColor:(UIColor*)textColor
{
CSLinearLayoutView *container = [[CSLinearLayoutView alloc] initWithFrame:frame];
container.orientation = CSLinearLayoutViewOrientationHorizontal;
UILabel *label = [[UILabel alloc] init];
label.textColor = textColor;
[label setText:labelTitle];
[label setFont:font];
[label sizeToFit];
CSLinearLayoutItem *itemLabel = [CSLinearLayoutItem layoutItemForView:label];
itemLabel.padding = labelLinearLayoutMakePadding;
CSLinearLayoutItem *itemView = [CSLinearLayoutItem layoutItemForView:view];
itemView.padding = viewLinearLayoutMakePadding;
[container addItem:itemLabel];
[container addItem:itemView];
return container;
}
example :
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 260, 40)];
UIView *customView = [LabledView create:CGRectMake(0, 0, 280, 40) view:textField
labelTitle:#"your label" viewLinearLayoutMakePadding:CSLinearLayoutMakePadding(0, 10, 0, 0)
labelLinearLayoutMakePadding:CSLinearLayoutMakePadding(10, 0, 0, 0)
font:[UIFont fontWithName:#"Helvetica" size:12] textColor:[UIColor blackColor]];
You can underline specific ranges of a string with NSAtttibutedString. You can setAttributedString to UILabel in ios6... So that's the way I'd do it, then it can indeed be in a single label with the desired parts underlined (or in a different font/colour/etc) only. Be careful when you look into attributed string, it's attributes dictionary uses different keys for working with UIKit (these are the ones you need here) to what it uses with CoreText
so I am trying to implement the following. I have a view, which has a sentence. Only part of the sentence links to another view. This is what it looks like:
I am a cat. Learn More
The Learn More would be a link (blue in color), which when clicked would open another view.
Currently I am using a UILabel to write "I am a cat". I realize that the best way to add selectors is to use a button, so "Learn More" should be a button?
Is there any way to write this sentence out without using two different UIComponents?
If not, then how do I make the UILabel and the UIButton completely horizontally aligned with each other?
The following is my code for the label in -layoutSubviews:
CGSize labelSize = [_label.text sizeWithFont:_label.font constrainedToSize:bounds.size lineBreakMode:_label.lineBreakMode];
_label.frame = CGRectMake(0, 0, bounds.size.width - kMarginForText, labelSize.height);
_label.center = CGPointMake(horizontalCenter, CGRectGetMaxY(_previousLabel.frame) + kDistanceBetweenPreviousAndCurrentLabel);
And the code for the label itself.
_label = [[UILabel alloc] initWithFrame:CGRectZero];
_label.text = "I am a cat";
_label.font = [UIFont systemFontOfSize:14];
_label.textAlignment = NSTextAlignmentCenter;
_label.numberOfLines = 0;
_label.lineBreakMode = UILineBreakModeWordWrap;
[self addSubview:_label];
Any help would be appreciated!
To answer your question about a single UIComponent, you could use a UILabel in conjunction with a UITapGestureRecognizer to create the intended effect. Granted this would make the whole label tappable... but having a bigger tap target area is almost never a bad thing.
In particular you would use an NSAttributedString to set the label text (NSAttributedString change color at end of string):
UILabel *label = [[UILabel alloc] init];
//Use initwithframe or setup your constraints after initialization here
label.attributedText = (your nsattributed string here)
Then to initialize the tap recognizer onto the UILabel you would do something like this:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(userDidTapLearnMore)];
label.userInteractionEnabled = YES;
[label addGestureRecognizer:tap];
What you want to do is to align them by their baselines, which you can easily do in Interface Builder by selecting them and choosing Editor > Align > Baselines, as shown in this illustration: