UIButton with two lines of text in the title (numberOfLines=2) - objective-c

I'm trying to make a UIButton that has two lines of text in its titleLabel. This is the code I'm using:
UIButton *titleButton = [[UIButton alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleButton.titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
[titleButton setTitle:#"This text is very long and should get truncated at the end of the second line" forState:UIControlStateNormal];
titleButton.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
titleButton.titleLabel.numberOfLines = 2;
[self addSubview:titleButton];
When I try this, the text only appears on one line. It seems the only way to achieve more than one line of text in UIButton.titleLabel is to set numberOfLines=0 and use UILineBreakModeWordWrap. But this doesn't guarantee the text to be exactly two lines.
Using a plain UILabel, however, does work:
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
titleLabel.text = #"This text is very long and should get truncated at the end of the second line";
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
[self addSubview:titleLabel];
Does anyone know how to make the UIButton work with two lines? Is the only solution to create a separate UILabel to hold the text, and add it as a subview of the button?

You don't need to add a UILabel to the UIButton. That's just extra objects and work.
Set these properties on the titleLabel of your button.
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2;//if you want unlimited number of lines put 0
Swift:
button.titleLabel!.lineBreakMode = NSLineBreakMode.ByWordWrapping
button.titleLabel!.numberOfLines = 2//if you want unlimited number of lines put 0

Updated answer for more recent iOS versions
Since this is the accepted answer, added #Sean's answer here:
Set these properties on the titleLabel of your button.
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2; // if you want unlimited number of lines put 0
Swift 3 and 4:
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.numberOfLines = 2 // if you want unlimited number of lines put 0
Original answer for an older version of iOS
If you want 2 lines of text on top of your UIButton you should add a UIlabel on top of it that does precisely that.
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
titleLabel.text = #"This text is very long and should get truncated at the end of the second line";
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
[myButton addSubview:titleLabel]; //add label to button instead.
Updated for interface builder solution
Added #Borut Tomazin's answer for a more complete answer.
Updated this part again since the answer of #Borut Tomazin was improved.
You can do this much easier, with no code required. In Interface Builder set Line Break on UIButton to Word Wrap. Than you can insert multiple lines of title. Just hit Option + Return keys to make new line. You will also need to add this to the User Defined Runtime Attribute in Interface Builder:
titleLabel.textAlignment Number [1]

You can do this much easier, with no code required. In Interface Builder set Line Break on UIButton to Word Wrap. Than you can insert multiple lines of title. Just hit Option + Return keys to make new line.
You will also need to add this to the User Defined Runtime Attribute in Interface Builder:
titleLabel.textAlignment Number [1]
It's that simple. Hope it helps...

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
[button setTitle: #"Line1\nLine2" forState: UIControlStateNormal];

To avoid completely the need to edit code, and thus the need to subclass your view, in Xcode5 and greater you can follow Borut Tomazin suggestion:
In Interface Builder (or storyboard) set Line Break to
Word Wrap. Than you can insert multiple lines of title. Just hit
Option + Return keys to make new line.
and then, in the User Defined Runtime Attributes you can add
Key path: titleLabel.textAlignment
Type: Number
Value: 1
Note: this may be not completely "future proof" since we are translating the UITextAlignmentCenter constant into its numerical value (and that constant may change as new iOS versions are released), but it seems safe in the near future.

You can modify the needed value directly from Storyboard.
Select the button, go to the identity inspector and add the following key-value pair in the "User defined runtime attributes" section:

Related

How do I create a horizontal line with text in the middle?

I'm very new to Objective C but I'm looking at the source code of an existing app so there's a lot here to sift through.
I'm trying to create something like this:
-------------- or --------------
...only with a solid horizontal line instead of the dashes.
I have the "or" text defined as this:
_orLabel = ^{
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.textColor = [UIColor blackColor];
label.font = [UIFont mainFontWithSize:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline].pointSize];
label.adjustsFontSizeToFitWidth = YES;
label.textAlignment = NSTextAlignmentCenter;
label.text = NSLocalizedString(#"or", nil);
[view addSubview:label];
return label;
}();
That's working great to get "or" to show up but I have no idea how to get the horizontal lines on either side.
I would subclass UILabel and override drawTextInRect:. The easiest way is to call super so that the text gets drawn. Now you are still in a graphics context (CGContext) so you can use ordinary Quartz drawing commands to draw your horizontal lines.
The simplest approach is to make use of certain Unicode characters that will give you a solid line.
label.text = #"───────── or ─────────";
That text is using a series of "BOX DRAWINGS LIGHT HORIZONTAL" characters (U+2500).
I would use IB to add a view on each side of the label. Make the views have a height of 1 or 2 with a black background, and use autolayout to make them size appropriately for the label and screen situation:
Make view #1 anchored to the left edge of the screen and the right side of the label.
Make view #2 anchored to the right edge of the screen and the left side of the label.
Make the 2 views and the label have the same vertical center.

UIButton setting frame not working?

I have written the following code for my app:
self.PlayButton = [[UIButton alloc] init];
//Setup Play Button
[self.PlayButton setTranslatesAutoresizingMaskIntoConstraints:NO];
self.PlayButton.frame = CGRectMake(self.view.frame.size.width * 0.38, self.view.frame.size.height * 0.666, self.view.frame.size.width * 0.48, self.view.frame.size.height * 0.29);
[self.PlayButton setBackgroundImage:[UIImage imageNamed:#"PlayButton.png"] forState:UIControlStateNormal];
[self.PlayButton.layer setMagnificationFilter:kCAFilterNearest];
[self.PlayButton addTarget:self action:#selector(PlayButtonMethod) forControlEvents:(UIControlEvents)UIControlEventTouchUpInside]
[self.view addSubview:self.PlayButton];
But when this code it run rather than the image appearing in a rather specific location it simply appears in the top left hand corner of the view. Almost like it had been set
self.PlayButton.frame = CGRectMake(0, 0, self.view.frame.size.width * 0.48, self.view.frame.size.height * 0.29);
It's odd because the width and height is put in correctly but for whatever reason the position of the button set by the CGRectMake is not taken into account. Ive done a bit of research into creating UIButtons in code and fro what I've seen not only has this happened to no-one else the code have written is perfectly liable.
Any help would be appreciated.
Thanks
Looks like ive found the fix:
Removing this line of code fixed the issue for me.
[self.PlayButton setTranslatesAutoresizingMaskIntoConstraints:NO];
not 100% sure why this was causing the problem but it fixed it.
When creating UIButtons using the standard alloc init method doesn't actually create a button. The method for creating and initializing a UIButton is called buttonWithType:. This creates a UIButton of the specified type if you use alloc init it will not work correctly, see the Apple Documentation for UIButton.
So you need to change line
self.PlayButton = [[UIButton alloc] init];
to
self.PlayButton = [UIButton buttonWithType:UIButtonTypeCustom];
buttonWithType: allows you to pass in an enum of UIButtonType so it will accept any of the following values :
UIButtonTypeCustom
UIButtonTypeSystem
UIButtonTypeDetailDisclosure
UIButtonTypeInfoLight
UIButtonTypeInfoDark
UIButtonTypeContactAdd
UIButtonTypeRoundedRect
If you don't pass it a UIButtonType the button will not be initialized as it will not know what type of button you want and it will not assume. Also check out the Apple Documentation for UIButtonType
Side Note
I'm just going to include this as a side note. Also have a read of the Apple Coding Conventions Documentation as I have noticed that you are using uppercase to start your variable names (i.e. PlayButton). Variable names should start with lowercase (i.e. playButton) and Class and Enum names should start with uppercase (i.e. UIViewController). It's always good to stick to conventions as it makes you code more readable and maintainable so if another developer comes to modify your code it is easy for them or even yourself to read.

Providing *hint* in text field in ios 7 as edittext field in android

I am creating a feedback form in an ios7 application and want to place few UITextFields which contain hints in the respective UITextField for name, phone number, email address, etc. I am using xcode 5 and ios7 for programming and creating application without use of storyboard.
The hint property is available in android for edit text field, but I am unable to find any such property in UITextField in ios 7.
Make use of the Placeholder text property.
Here's an example:
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(10, 10, 100, 50)];
textField.font = [UIFont fontWithName:#"Arial" size:20];
textField.placeholder = #"Your hint here.";
If you are using a storyboard or XIB, this property can be edited there also.
Also, if you want to use custom attributes for the placeholder, you can use the attributedPlaceholder property:
NSAttributedString *attribString = [[NSAttributedString alloc] initWithText:#"Your hint here." attributes:#{NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue" size:16.0]}];
textField.attributedPlaceholder = attribString;

Change font color of UITextView

I have a UITextView where the user can input text. Say the user has already inputted a value. How can I change the font color of that already typed text and future typed text to a different one with the click of a button?
I already have it set up where I can change the color of the text but it only works if I choose a color BEFORE I start typing. After I start typing and I attempt to change the color, it doesn't do anything.
I have this:
-(IBAction)changeInkColor:(id)sender
{
[inkTextField setTextColor:[UIColor greenColor]];
inkTextField.text=#"text";
}
and that actually works and displays "text" in green only if there is no text already in the view. However if I type something in and then hit this button, nothing happens.
I just tried that and I had no problems. I set up a button that called [myTextView setTextColor:[UIColor redColor]];
After typing a bit with black text color, I pressed the button, and everything turned red. Then I continued typing, all in red.
Are you using setTextColor: to do this also?
In the end, setTextColor: is the answer, there's an important detail missing from the earlier answers: To get this to work in iOS 8, I had to set the color =after= I set the text.
Hence,
- (void)viewDidLoad
{
[super viewDidLoad];
_myTextView.textColor = [UIColor whiteColor];
_myTextView.text = #"yadda yadda yadda...";
// etc., snip
Did NOT work, while
- (void)viewDidLoad
{
[super viewDidLoad];
_myTextView.text = #"yadda yadda yadda...";
_myTextView.textColor = [UIColor whiteColor];
// etc., snip
DID work. This strikes me as a bug in iOS 8, which I will write up.
You can fix this (at least in Xcode 8.2) in IB by toggling the textColor button (6th button in the row). With this button selected, if you set the textColor programmatically before you enter text in the view, the color will "stick." I have not found an elegant way to set this on the text view programatically.
However you can also work around this in code:
textView.text = #" ";
textView.textColor = UIColor.redColor;
textView.text = #"";
I had the same problem as you, then I realised that the text was not changing colour, and was red by default because I was doing:
placeholder = #"Welcome";
instead of
WelcomeField.text = #"Welcome";
Hope it helps
use attributed text of UITextField
NSAttributedString *string = [[NSAttributedString alloc]initWithString:self.textField.text attributes:#{NSForegroundColorAttributeName:color}];
self.textField.attributedText = string;
Very interestingly, while
[_nameLabel setTextColor: [UIColor redColor]];
didn't work,
_nameLabel.textColor = [UIColor redColor]];
worked. Hope it helps for others. Cheers.

UIButton multi-line text with tail truncation

I have found similar questions that ask how to have multi-line text on a UIButton, and the solution is to set
[myUIButton.titleLabel setLineBreakMode:UILineBreakModeWordWrap];
[myUIButton setTitle:myTitle forState:UIControlStateNormal];
However, this results in the button title taking up many lines. I have tried restricting the number of lines using
[myUIButton.titleLabel setNumberOfLines:2];
but this does not have any affect on the resulting number of lines.
Is there a way to limit the lines word wrapped to 2 lines on the UIButton title, and then have the tail truncated with "..."?
By setting lineBreakMode before numberOfLines your desired result can be achieved…
This is because lineBreakMode seems to cancel out numberOfLines set hence we are doing it in this order.
Objective-C:
[button.titleLabel setLineBreakMode: UILineBreakModeTailTruncation];
[button.titleLabel setNumberOfLines:2];
[button setTitle:myTitle forState:UIControlStateNormal];
Swift 3:
from Xcode 6 and above UILineBreakMode is replaced by NSLineBreakMode
button.titleLabel?.lineBreakMode = NSLineBreakMode.byTruncatingTail
button.titleLabel?.numberOfLines = 2
button.setTitle(myTitle, for: UIControlState.normal)
I know its been a while since the question was first asked, but I came across the same problem and endend up with a simple but functional solution after considering the answer posted
here.
The solution that worked for me was the following:
// Set the line break mode to word wrap so it won't truncate automatically
[button.titleLabel setLineBreakMode: UILineBreakModeWordWrap];
// Call a method that truncates the string I want to use
[button setTitle:[self truncateString:myButtonText] forState:UIControlStateNormal];
And the truncateString method:
- (NSString *)truncateString:(NSString *)stringToTruncate
{
if ([stringToTruncate length] > 50)
stringToTruncate = [[stringToTruncate substringToIndex:50] stringByAppendingString:#"..."];
return stringToTruncate;
}
So basically I calculated the number of characters that would work for my button, and then forced any string longer than that to have the '...' at the end. I know its not the ideal solution but I guess it can work for some of us, I hope it helps.
[button.titleLabel setNumberOfLines:2];
[button.titleLabel setLineBreakMode: UILineBreakModeTailTruncation];
[button setTitle:myTitle forState:UIControlStateNormal];
it does it for me! :D
cheers!!