UIButton title appears with dots when set programatically - ios

When I set the title of the UIButton in the xib, it works fine, but when I set the same text programatically to the title of the button it is trimmed.
BUY THIS FILM FOR 20.00$ -> BUY THIS FI...FOR 20.00$

Try this way:
[_button setTitle:#"BUY THIS FILM FOR 20.00$" forState:UIControlStateNormal];

What is displayed in interface builder when you edit the xib is not guaranteed to look exactly like when it is loaded on the simulator or device.
Solution: just make your Button a little bit wider.
Also, double check that the text is exactly the same as in IB.

Try this way:
btnObj.titlelabel.minimumFontSize = 8.0; // or some more adequate size
btnObj.titleLabel.adjustsFontSizeToFitWidth = YES;

Related

Segment Bar in iOS accross different Size classes

I'm using UISegmentController (default provided by iOS). I want to show text for iPad or iPhone landscape view. Where as in case of iPhone, I want to show icons (not text) in the same segment bar.
Is it possible? If yes, then how can I achieve this in story board or programmatically?
You can achieve this by adding UISegmentedControl programatically.
Code is as follows in controller viewWillAppear method,
- (void)viewWillAppear:(BOOL)animated {
UISegmentedControl * cntrl = [[UISegmentedControl alloc] initWithItems:#[[UIImage imageNamed:#"Circle"],#"2"]];
cntrl.frame = CGRectMake(30, 100, 200, 50);
[self.view addSubview:cntrl];
}
With above code we're creating segment control with one image in first segment and text in second segment. Check attached screenshot.
Use following code to check either device is iPad or iPhone
-(BOOL) isiPad {
return UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad;
}
Based on the type of the device, customise segment control.
For existing segment control, when you want to set image,
[cntrl setImage:[UIImage imageNamed:#"Tick"] forSegmentAtIndex:0];
use above method by specifying which image you want to set at particular segmentIndex.
At the same way when you want to set text at particular index, use
[cntrl setTitle:#"Hello" forSegmentAtIndex:0];
It doesnt seem possible to use the storyboard completely on its own to do this kind of functionality, but a combination of this and this inside your viewDidLoad might get you want you want

Difference between setTitle:forState: and titleLabel.text

After looking over the internet and other SO questions(this one is great iOS: UIButton titleLabel -- does it do anything at all?), it is unclear to me what is the difference between these two, more accurately, how these two work.
I know that setTitle:forState: let me set text of the button for different states(Normal, Disabled,Highlighted etc.). I know, as well, that titleLabel is read only, but its properties are read/write.
At this point you might ask: What is the problem then?
I will explain it through example. I have following hierarchy:
UITableViewCell - MyView - MyButton
MyView is xib in which, through interface builder, I set button. When I set buttons title like:
self.myButton.titleLabel.text = #"Something"; // some string I get from server
It works. But if I try the similar approach when only MyView is included (somewhere else in the project) and try:
myView.myButton.titleLabel.text = #"Something else";
It doesn't work. Let me be more specific. In one part of the second(even in viewDidApper) buttons title is what I want. After that, the buttons label returns to its default value. The one I set in the interface builder. When I change to
[myView.myButton setTitle:#"Something else" forState:UIControlStateNormal];
It works as expected.
What I want to know is why does this happen? It is unclear to me why does this glitch occurs with the title? Is this strange thing documented somewhere(looked over apple documentation)? Is it possible to get implementation of setTitle:forState:?
I'm not sure how the internals of UIButton are actually implemented but this is a guess. There are times when iOS needs to redraw the button ie. the button is tapped so the button's state changes (let's say from UIControlStateNormal to UIControlStateHighlighted). Then iOS would find the title associated to UIControlStateHighlighted then display that text by using something like.
myButton.titleLabel.text = #"Title for UIControlStateHighlighted";
Sample scenario:
[myButton setTitle:#"Normal" forState:UIControlStateNormal];
[myButton setTitle:#"Highlighted" forState:UIControlStateHighlighted];
// somewhere in the code, you call this to change the label
myButton.titleLabel.text = #"Something else";
// when user taps the button, iOS will do something like
myButton.titleLabel.text = #"Highlighted"; // will overwrite "Something Else"
// when user releases, iOS will again do something like
myButton.titleLabel.text = #"Normal"; // will overwrite "Highlighted"
so it's required to use setTitle:forState: in order to associate the given title to a certain state. The instances where iOS redraws the button is of course not limited to the the user interacting with the button. It could also be triggered by layout changes.
You should not use button.titleLabel.text = to set the button title.
The documentation for the titleLabel property says
Although this property is read-only, its own properties are read/write. Use these properties primarily to configure the text of the button. For example:
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.titleLabel.font = [UIFont systemFontOfSize: 12];
button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
Do not use the label object to set the text color or the shadow color. Instead, use the setTitleColor(:for:) and setTitleShadowColor(:for:) methods of this class to make those changes. To set the actual text of the label, use setTitle(_:for:) (button.titleLabel.text does not let you set the text).
I normally don't set button titles in interface builder, but do it in the viewDidLoad, and get the title from Localizable.strings..
You must use setTitle:forState and setTitleColor:forState to change text and color. All other label properties can be changed directly though.
"Do not use the label object to set the text color or the shadow color. Instead, use the setTitleColor:forState: and setTitleShadowColor:forState: methods of this class to make those changes."
-source

AspectFill does not fill the UIImageView

I have a button that has contentMode set to UIViewContentModeScaleAspectFill. I set it like this:
self.itemImage.imageView.contentMode = UIViewContentModeScaleAspectFill;
I also set it to Mode - Aspect Fill in IB for the button, just in case. And when I set the image, I DON'T set is as a background image:
[self.itemImage setImage:image forState:UIControlStateNormal];
However, occasionally my image does not fill the button (which I want it to do), like in this case:
See grey spaces on each side. Occurs on both iOS 6 and 7.
Any ideas?
At long last, I managed to find the solution that works in Alfie's answer to this SO question.
In short, if your UIButton (or its hidden imageView) does not respond to contentMode, use this code:
self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

How to create and add UIButton with multiline label from code using autolayout?

There's are a lot of links how to size a label, however there's a lack of info how to resize UIButton according to its label size. Currently, I have screen view set with autolayout (all the system constraints are added from IB) and everything works fine, but need to add dynamic content at the bottom of the screen. I need to create and add random number of buttons with random length titles. So, here's code fragment for creating and adding the buttons:
// Loop
UIButton *myButton = [UIButton new];
UIButton.frame = CGRectMake(0, previousButtonOriginY, self.view.bounds.size.width, 20);
myButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
myButton.titleLabel.textAlignment = NSTextAlignmentLeft;
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[myButton setTitle:#"very long title..." forState:UIControlStateNormal];
myButton.titleLabel.numberOfLines = 0;
[self.footerView addSubview:myButton];
The problem is the frame height of the button stays 20px but the label string is shown on three lines and so overlaps with the other button title. If I add [myButton sizeToFit] then button width is resized to fit all the text into one line and so the title goes beyond the screen.
If I add [myButton sizeThatFits:CGSizeMake(320, 100)] then resize is not working at all. I know sizeToFit should not be called at all because it's not the part of autolayout, however need suggestions on that how easily to make button fit its label to screen 320 width.
I feel I need to add system constraints from code, but haven't done that before, so not sure how it should look like. I probably need a ton of constraints to be added from code in order to get this simple thing working :)
Instead of using Autolayout, you could just use a collection view which better options for you to lay out elements such as buttons.
It is better able to handle layouts under rotation as well.
Or you can use this code, it worked for me...
For example, substitute your desired padding values here:
UIButton* myButton = [[UIButton alloc] init];
// setup some autolayout constraints here
myButton.titleEdgeInsets = UIEdgeInsetsMake(-desiredBottomPadding,
-desiredRightPadding,
-desiredTopPadding,
-desiredLeftPadding);
Combined with the right autolayout constraints, you end up with an auto-resizing button which contains an image and text!
For this kind of customizations you'll need to create a subclass of UIButton. In the subclass you can add a customized label which benefits your needs. You can also override to setTitle:forState method to automatically update your customized label.

How to make UIButton's text alignment center? Using IB

I can't set the title of UIButton using IB as center. My title is multi line.It is giving like this one
But I want like this one
I have given space in this but I don't want to do that. As it is not aligned exactly for some cases and I know there is a property of UILabel to set the alignment but I don't want to write a code for that.. just want to set everything from IB.
Thanks
This will make exactly what you were expecting:
Objective-C:
[myButton.titleLabel setTextAlignment:UITextAlignmentCenter];
For iOS 6 or higher it's
[myButton.titleLabel setTextAlignment: NSTextAlignmentCenter];
as explained in tyler53's answer
Swift:
myButton.titleLabel?.textAlignment = NSTextAlignment.Center
Swift 4.x and above
myButton.titleLabel?.textAlignment = .center
Use the line:
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
This should center the content (horizontally).
And if you want to set the text inside the label to the center as well, use:
[labelOne setTextAlignment:UITextAlignmentCenter];
If you want to use IB, I've got a small example here which is linked in XCode 4 but should provide enough detail (also mind, on top of that properties screen it shows the property tab. You can find the same tabs in XCode 3.x):
Solution1
You can set the key path in the storyboard
Set the text to your multiline title e.g. hello ⌥ + ↵ multiline
You need to press ⌥ + ↵ to move text to next line.
Then add the key path
titleLabel.textAlignment as Number and value 1, 1 means NSTextAlignmentCenter
titleLabel.numberOfLines as Number and value 0, 0 means any number of lines
This will not be reflected on IB/Xcode, but will be in centre at run time (device/simulator)
If you want to see the changes on Xcode you need to do the following: (remember you can skip these steps)
Subclass the UIButton to make the button designable:
import UIKit
#IBDesignable class UIDesignableButton: UIButton {}
Assign this designable subclass to the buttons you're modifying:
Iff done right, you will see the visual update in IB when the Designables state is "Up to date" (which can take several seconds):
Solution2
If you want to write the code, then do the long process
1.Create IBOutlet for button
2.Write code in viewDidLoad
btn.titleLabel.textAlignment = .Center
btn.titleLabel.numberOfLines = 0
Solution3
In newer version of xcode (mine is xcode 6.1) we have property attributed title
Select Attributed then select the text and press centre option below
P.S. The text was not coming multiline for that I have to set the
btn.titleLabel.numberOfLines = 0
For UIButton you should use:-
[btn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
For ios 8 and Swift
btn.titleLabel.textAlignment = NSTextAlignment.Center
or
btn.titleLabel.textAlignment = .Center
For those of you who are now using iOS 6 or higher, UITextAlignmentCenter has been deprecated. It is now NSTextAlignmentCenter
EXAMPLE: mylabel.textAlignment = NSTextAlignmentCenter; Works perfectly.
For swift 4, xcode 9
myButton.contentHorizontalAlignment = .center
Assuming that btn refers to a UIButton, to change a multi-line caption to be centered horizontally, you can use the following statement in iOS 6 or later:
self.btn.titleLabel.textAlignment = NSTextAlignmentCenter;
For Swift 4:
#IBAction func myButton(sender: AnyObject) {
sender.titleLabel?.textAlignment = NSTextAlignment.center
sender.setTitle("Some centered String", for:UIControlState.normal)
}
UITextAlignmentCenter is deprecated in iOS6
Instead you can use this code:
btn.titleLabel.textAlignment=NSTextAlinmentCenter;
For Swift 3.0
btn.titleLabel?.textAlignment = .center
Try Like this :
yourButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
yourButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
Actually you can do it in interface builder.
You should set Title to "Attributed" and then choose center alignment.
You can do this from storyboard.
Select your button. Set Line Break 'Word Wrap', Set your title 'Plain' to 'Attributed'.
Select 'Center alignment'. This part is important => Click ...(More) Button. And select line breaking mode to 'Character Wrap'.
UIButton will not support setTextAlignment. So You need to go with setContentHorizontalAlignment for button text alignment
For your reference
[buttonName setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];

Resources