I want to make a UIButton with type UIButtonTypeCustom (for the shape). I want to assign the title using button.titleLabel because I need to specify the font. The following code looks like it should work, but doesn't -- no label shows up, period.
UIImage *editButtonImage = [UIImage imageNamed: #"editButton.png"];
float width = editButtonImage.size.width;
float height = editButtonImage.size.height;
UIButton *editButton = [UIButton buttonWithType: UIButtonTypeCustom];
editButton.frame = CGRectMake(0, 0, width, height);
[editButton setBackgroundImage: editButtonImage forState: UIControlStateNormal];
editButton.adjustsImageWhenHighlighted = YES;
editButton.titleLabel.text = #"Edit";
editButton.titleLabel.textColor = [UIColor whiteColor];
editButton.titleLabel.textAlignment = UITextAlignmentCenter;
editButton.titleLabel.font = [UIFont fontWithName: #"Helvetica" size: 14];
[self.view addSubview: editButton];
Everyone always says to use setTitle:forState: but that gives you a font I don't like. The titleLabel method is NOT deprecated -- it should work.
I have run into this several times before and always just worked around it, but I'd really like to figure it out. Any ideas?
Setting the titleLabel's text property like that has no effect. Instead, call -setTitle:forState: on the button:
[editButton setTitle:#"Edit" forState:UIControlStateNormal]
The reason for this is because the button can have different titles for different states (e.g., UIControlStateDisabled, UIControlStateHighlighted). Setting a property for the UIControlStateNormal control state will apply to all the states if you don't specify the others explicitly.
Per the documentation for UIButton:
This class provides methods for setting the title, image, and other appearance properties of a button. By using these accessors, you can specify a different appearance for each button state.
You can customize label's color and shadow color based on the state. See -setTitleColor:forState and -setTitleShadowColor:forState, respectively. The rest of the properties on titleLabel, such as textAlignment and font, should work as you have them set now and should apply to all the control states.
Specifically, see the documentation for UIButton's titleLabel property: https://developer.apple.com/documentation/uikit/uibutton/1623992-titlelabel
titleLabel itself is read-only, but that doesn't mean you can't change the values of its own properties, such as font, line break mode, etc.
Here's how I worked it out using Swift 4.2.
counterButton.setTitle("Start Counter",
for:UIControl.State.normal)
Related
I have seen a bunch of similar questions, but noone got the answer I am looking for. When I use this code to make a UIButton and set it's titleLabel, the UIButton appear, but the titleLabel won't appear.
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[button setBackgroundImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal];
button.titleLabel.text = #"Title";
button.titleLabel.font = [UIFont fontWithName:#"System-Bold" size:25.0f];
[self.view addSubview:button];
This code displays the button, but not the titleView, it's title. Why can that be? I am developing for iOS 6 and higher.
NOTE 1: I am not looking for an option like this:
[button setTitle:#"Title" forState:UIControlStateNormal];
Because I have to use the titleLabel to set it's font and fontSize.
NOTE 2: I can't create a UILabel and add it as a subView of the button. Since the button is later animating.
You always need to specify ControlState when updating button's title!
There are four possible values for UIButtons:
UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
so for example:
[button setTitle:#"Title" forState:UIControlStateNormal];
and then you can set custom settings for titleLabel:
[button.titleLabel setFont:[UIFont fontWithName:#"Zapfino" size:20.0]];
[button.titleLabel setTextColor:[UIColor blueColor]];
[button setTitle:#"Title" forState:UIControlStateNormal];
Is the correct way to set the title string.
titleLabel is used to set the font and color.
Try using...
[button setNeedsLayout];
[button layoutIfNeeded];
It will force button to update the layout.
If in the storyboard with a custom button image from assets like me
Check-in Attribute inspector
Check-in Attribute inspector set asset image as a background
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).
The titleLabel property returns a value even if the button has not been displayed yet. The value of the property is nil for system buttons.
in swift :
button.setTitle("your text", for: .normal)
button.setTitleColor(.white, for: .normal)
TLDR - try this saveButton.titleLabel?.layer.zPosition = 10
This was a frustrating one for me. I created a UIButton programmatically, added constraints, and added a gradient background (this is what caused my problem...I think). Then I needed to update the font:
saveButton.titleLabel?.font = UIFont.systemFont(ofSize: 20, weight: .semibold)
saveButton.setTitle("Save", for: .normal)
Notice I'm setting the title in the correct way. But still, no title showing. The craziest part - when I clicked "Debug View Hierarchy" I could see the title right there! If I didn't change the font, the title showed as well. Confusing. Then I added this (literally flinging spaghetti and seeing what stuck):
saveButton.titleLabel?.layer.zPosition = 10
It worked. It seems like some combination of gradient background, setting the font, etc was putting the button's internal title label at the bottom of its layers.
I'm working on customizing the appearance of navigation controllers in my app to look like the following:
As I've discovered after a few hours of SO research, there are a ton of different ways of doing it, some really hackish, some much less so. I'm interested in finding out the Apple-blessed / most elegant way of achieving this that will lead to the least amount of pain down the road as the app grows. Some approaches I've looked into so far:
1) I changed the background / height of the navigation bar by applying an image through [UINavigationBar appearance], seems to have worked fine.
UIImage *navBarImage = [UIImage imageNamed:#"navigation-bar.png"];
[[UINavigationBar appearance] setBackgroundImage:navBarImage
forBarMetrics:UIBarMetricsDefault];
Seems like the most "modern" way of achieving background/height change, although it most likely doesn't survive an orientation change. Any improvements that could be made here?
2) I replaced the default back button with the following in the viewDidLoad of the pushed view
// Set the custom back button
UIImage *buttonImage = [UIImage imageNamed:#"back.png"];
//create the button and assign the image
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
//set the frame of the button to the size of the image (see note below)
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
// offset the back button
button.contentEdgeInsets = UIEdgeInsetsMake(10, 5, -10, -5);
//create a UIBarButtonItem with the button as a custom view
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
I'm not very pleased with this solution because it leaves customization of the bar to the controller on top of the navigation stack. From the Apple docs it would seem like they'd prefer you to subclass the UINavigationBar altogether and replace it once and for all in the navigation controller:
You can also specify a custom UINavigationBar subclass by using the initWithNavigationBarClass:toolbarClass: method to initialize the navigation controller.
Would that be the advised route? I was NOT able to replace the default Back button of the UINavigationBar through [UIBarButtonItem appearance] as it still attempts to display text in the button, and when you remove the text, the button isn't displayed at all. Suggestions?
3) The page title should be replaceable with another view through navigationItem.titleView. Anything better out there?
Thanks!
1) You should set two images, for two UIBarMetrics (UIBarMetricsDefault and a separate image for UIBarMetricsLandscapePhone). Thus
UIImage *navBarImage = [UIImage imageNamed:#"navigation-bar.png"];
UIImage *navBarImage_Landscape = [UIImage imageNamed:#"navigation-bar-landscape.png"];
[[UINavigationBar appearance] setBackgroundImage:navBarImage
forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:navBarImage_Landscape
forBarMetrics:UIBarMetricsLandscapePhone];
2) You could either subclass UINavigationBar (as you've also mentioned and that would be the default Apple way). Or if it's just the button, maybe you could hack its behaviour by passing in " " (empty text)
3) Not sure what you meant. You could setTitle of the navigation bar and it would show whatever title you want. Or you should be able to plug in another view for titleView
Note that setBackgroundImage is iOS 5.0 and later.
I initiated my button like this:
meetingPointButton = [UIButton buttonWithType:UIButtonTypeCustom];
[meetingPointButton setTitle:#"Alpha" forState:UIControlStateNormal];
[meetingPointButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
Afterwards I change its title and when doing so also want to alter the title color. I am using following code:
[meetingPointButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[meetingPointButton setTitle:#"Beta" forState:UIControlStateNormal];
The title changes to "Beta" but its color stays light gray. Any ideas how to solve that issue?
As prince said use:
meetingPointButton.titleLabel.textColor = [UIColor blackColor];
Leaving out forState:UIControlStateNormal makes the button switch right away instead of the next time it recieves to go to UIControlStateNormal. Knowing this you could also just set the button to UIControlStateNormal after your original code.
Try this:
meetingPointButton.titleLabel.textColor = [UIColor blackColor];
to change text color.
For people that might be coming to this question on the basis of the title, one reason you might not see an effect when you change the color of the title is because the UIButton's string might be an NSAttributedString. UIButton has special methods to set an attributed string for the title and when a title is set that way setting the title text color has no effect. You need to change the attributed title NSAttributedString instead.
I'm adding a UIButton as a subView in a popup and I can't get it to show up semi-transparently. The background for the main view of the popup does show up semi-transparently, but this UIButton stays fully opaque. Can someone tell my why the code below is not working? Thanks.
UIButton* checkButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
checkButton.frame = CGRectMake(187, 288, 30, 30);
[checkButton setTitle:#"?" forState:UIControlStateNormal];
checkButton.opaque = NO;
[checkButton setBackgroundColor:[UIColor colorWithWhite:1.0 alpha:0.3]];
[checkButton setTitleColor: [UIColor colorWithRed: 51 / 255.0 green:0 blue: 153 / 255.0 alpha:0.5] forState: UIControlStateNormal];
[checkButton addTarget:self action:#selector(check) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:checkButton];
The background for a RoundedRect button is the rectangle in which it is located, and not the button itself. Try changing the background color to red or something equally visible and you will see that the background is only visible between the rounded corners of the button and the rectangular frame in which the button is set. Sadly, you cannot change the color of the button, which is what most people think they are doing when they change the backgroundColor property.
To change the button color, you will need to use UIButtonTypeCustom.
try setting your UIColor to
myButton.layer.backgroundColor = [UIColor x..]
you'll need a
#import <QuartzCore/QuartzCore.h>
im pretty sure the colour in the rounded rect button is in the layer, not in the regular background, this is why people struggle to change its colour..
alternately, put the alpha on the views colour back to 1 and hit the views alpha property, that'll certainly do the lot in one move.
PengOne is right – setting the background color doesn't change the color of the rounded rect. It only affects the corners around the rect.
But you can also just set the button's alpha property to something less than one. Try 0.7 to make the view semi-transparent.
Try using UIButtonTypeCustom instead UIButtonTypeRoundedRect as the button type.
UIButtonTypeRoundedRect is weird. Setting background /alpha etc on it only changes the background of the rectangle into which the button is rendered.
You could change the button type to UIButtonTypeCustom and then use QuartzCore to set cornerRadius to make it appear rounded.
I have a UIToolbar that I've customized with my own background image. Consequently, the built-in UIBarButtonItem appearance doesn't work for me, so I'm using images that are already prepared to show in the bar. I create a custom button item with this method:
+ (UIBarButtonItem *)customWithImage:(UIImage *)image enabled:(BOOL)enabled target:(id)target action:(SEL)selector {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//I've tried different values for the frame here, but no luck
button.frame = CGRectMake(0, 0, 44, 44);
button.enabled = enabled;
button.showsTouchWhenHighlighted = YES;
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
[button setImage:image forState:UIControlStateNormal];
UIBarButtonItem *it = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
//Tried changing this, to no avail
it.width = 32.f;
return it;
I have one button on the left and one on the right and I'm trying to make it so that if you tap on the far left or far right of the UIToolbar, the corresponding button is tapped. However, with these custom buttons, the hit targets do not extend all the way to the edges of the UIToolbar, but are inset from the sides:
http://skitch.com/andpoul/d1p8g/hit-targets
Any help greatly appreciated!
UIBarButtonItem.width might be ignored if you're using a custom view (it probably just uses the width of the view).
A lame hack is to make the toolbar wider (so it sticks outside the screen) and add transparent edges to the background image to compensate. This brings the buttons closer to the edge of the screen.
An alternative is just to use a UIImageView with UIButton subviews.
I think the only way you will have to go is to make buttons wider (change image by adding some from left for one and right for another) and adjust size...