The most common fix to this issue is "Set as background image, not normal image"
In my case I put background images on all my buttons, if it is a locked object, I add the image of a lock on top of the background image. The image looks as expected, but in that case it does not show the title of the image.
UIButton *button = (UIButton *)view;
if(self.currentArray[index][2] != NULL) //before it was if (button == nil)
{
NSString *name = [[NSString alloc] initWithString:self.currentArray[index][2]];
UIImage *image = [UIImage imageNamed:self.currentArray[index][5]];
button = [UIButton buttonWithType:UIButtonTypeCustom];
if ([self.currentArray[index][6] isEqualToString:#"true"]) {
//show it
}else{
//-------------------------
//--THE PROBLEM HAPPENS IF THIS PIECE OF CODE IS EXECUTED, SPECIFICALLY setImage
//-------------------------
button.alpha = 0.5;
UIImage *locked = [UIImage imageNamed:#"locked.png"];
button.imageEdgeInsets = UIEdgeInsetsMake(15, 15, 15, 15);
[button setImage:locked forState:UIControlStateNormal];
}
button.frame = CGRectMake(0.0, 0.0, 56, 56);
button.tag = index;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
UIEdgeInsets buttonInset = UIEdgeInsetsMake(30, -30, -25, -30);
[button setTitleEdgeInsets:buttonInset];
[button setTitle:name forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize: 8];
[button addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
Here is the images without lock and with lock:
The answer is here.
Quoting: "It appears that when you put an image in the button. the text is shoved off to the right. Use the edge settings to bring it back over the image."
What you have to do is play around with the title inset in order to bring the title label back to the right position.
I would suggest having something like an extraLeftInset variable that defaults to 0 and that is set to the right value in the else branch.
The answer above suggest to use this formula [Edge inset for Title] Left = -(imageWidth * 2), so the value should be -512 since you say that the image normally is 256. It would be nicer to evaluate it at runtime inspecting the size of the image though.
Hope this helps :)
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, 0.0, 0.0);
left side negative padding for titleLabel. Padding value must be equal to the image width
Related
I have one UIButton. In that UIButton i have to show text and image. Image should be displayed after the text. Based on text i want to adjust the button frame.
See the image. After the text "I am a Button", i want to add a image like arrow.
UIButton *titleButton = [UIButton buttonWithType:UIButtonTypeCustom];
NSString *name = #"I am a button";
titleButton.titleLabel.text = [NSString stringWithFormat:#"%#", name];
titleButton.titleLabel.textColor = [UIColor whiteColor];
CGSize stringSize = [name sizeWithAttributes:#{NSFontAttributeName: [UIFont fontWithName:#"MyriadPro-Cond" size:24]}];
CGRect frame = CGRectMake(300, 30, stringSize.width, 30);
//frame.size.width = stringSize.width;
[titleButton setFrame:frame];
UIImageView *image = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"home.png"]];
image.frame = CGRectMake(stringSize.width, 14, 20, 13);
titleButton.imageEdgeInsets = UIEdgeInsetsMake(0, 0, stringSize.width+20, 0);
[titleButton addSubview:image];
I written code like this. But it is not working. Anyone can make it correct. Thanks in advance
You dont have to add a UIImageView over the UIButton to get this behaviour. The UIButton has itself has some properties. Set the orange image as the background image of the button, set the arrow image as the image of the button. Then adjust the insets of the title and the image of the button to move the title to the left and the arrow image to the right.
[btn setBackgroundImage:[UIImage imageNamed:#"orange_bg"] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:#"arrow"] forState:UIControlStateNormal];
[btn setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, -60, 0)];
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 125, 0)];
You have to adjust the insets according to your image and button sizes.
I have two buttons. They both have the same image except the fact that one of the images is flipped. I don't want to have an excess image in the bundle of my app if it's possible to create image programmatically so i create my buttons like this:
UIImage *forwardImage = [UIImage imageNamed:rewind_btn_img];
UIImage *rewindImage = [UIImage imageWithCGImage:forwardImage.CGImage
scale:forwardImage.scale
orientation:UIImageOrientationUpMirrored];
NSArray *images = #[rewindImage, forwardImage];
for (int i = 0; i < 2; i++)
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = images[i];
btn.frame = CGRectMake(0.f, 0.f, image.size.width, image.size.height);
btn.center = CGPointMake(self.playButton.center.x + (i == 0 ? - 80.f : 80.f) * TGScaleMultiplier, self.playButton.center.y);
btn.tag = i + 1;
[btn setBackgroundImage:image forState:UIControlStateNormal];
[btn addTarget:self action:#selector(rewindButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
The problem is that when i press the button whose image is rewindImage it shows the original image, flipped to the other side. Am i doing something incorrectly here? Is there any workaround?
Not sure exactly why that UIImage:imageWithCGImage is flaky but I tried another method for mirroring the image and when applied to the button it works great. So get rid of the UIImage:imageWithCGImage line and use this:
UIImage *rewindImageBase = [UIImage imageNamed:rewind_btn_img];
UIGraphicsBeginImageContext(rewindImageBase.size);
CGContextRef current_context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(current_context, rewindImageBase.size.width, 0);
CGContextScaleCTM(current_context, -1.0, 1.0);
[rewindImageBase drawInRect:CGRectMake(0, 0, rewindImageBase.size.width, rewindImageBase.size.height)];
UIImage *rewindImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
That should do it.
if it initially looks right, but changes when you press it, Try setting the image for all button states, or at least for the normal state and the selected state.
[btn setBackgroundImage:image forState:UIControlStateNormal];
[btn setBackgroundImage:image forState:UIControlStateSelected];
you could also try setting the showsTouchWhenHighlited but the first way should work
[btn setShowsTouchWhenHighlighted:NO];
EDIT: try also setting the highlighted state, this works for me
[btn setBackgroundImage:image forState:UIControlStateHighlighted];
As seen on the picture I have 2 buttons with 0.5 alpha and 1 alpha. I want to change the alpha of the title in the first picture to 1. Is this possible?
So far I tried these which did not work:
button.titleLabel.alpha = 1;
[button setTitleColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1] forState:UIControlStateNormal];
UIButton *button = (UIButton *)view;
if(self.currentArray[index][2] != NULL) //before it was if (button == nil)
{
NSString *name = [[NSString alloc] initWithString:self.currentArray[index][2]];
UIImage *image = [UIImage imageNamed:self.currentArray[index][5]];
button = [UIButton buttonWithType:UIButtonTypeCustom];
int extraLeftInset = 0;
if ([self.currentArray[index][6] isEqualToString:#"true"]) {
//show it
}else if([self.currentArray[index][7] isEqualToString:#"true"]){
}else{
UIImage *locked = [UIImage imageNamed:#"fruitify_locked.png"];
button.imageEdgeInsets = UIEdgeInsetsMake(15, 15, 15, 15);
[button setImage:locked forState:UIControlStateNormal];
extraLeftInset = - 256; //size of locked
button.backgroundColor = [UIColor clearColor];
button.alpha = 0.5;
}
button.frame = CGRectMake(0.0, 0.0, 56, 56);
button.tag = index;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
UIEdgeInsets buttonInset = UIEdgeInsetsMake(30, -2 + extraLeftInset, -20, -2);
[button setTitleEdgeInsets:buttonInset];
[button setTitle:name forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize: 8];
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[button addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
One way to do this would be to adjust the alpha value of your image. That can be done by passing your image to this method,
-(UIImage *)image:(UIImage *) image withAdjustedAlpha:(CGFloat) newAlpha{
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
[image drawAtPoint:CGPointZero blendMode:kCGBlendModeCopy alpha:newAlpha];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The alpha setting affects a view and all it's subviews. If you set the alpha on a button, every part of the button will have that alpha value.
You have a couple of possible options.
You could create a custom subclass of UIButton that managed a UILabel that was a sibling view of the button in the view hierarchy. That would get messy in several ways however. The normal button title methods wouldn't work, and you would have to introduce your own control logic to remove the button label from the superview if the button was removed
You might also try manipulating the alpha property of the button's image view. (The buttons' imageView property is read-only, but you CAN still make changes to the attributes of the image view in that property. You would need to test to make sure that the button doesn't mess up the image view's alpha property when it swaps images for the different button states (highlighted, selected, etc.) You would probably also need to set the opaque property on the button to NO, and perhaps on the image view as well. (You'll need to experiment.)
BTW, I like you trick of offsetting the button title using setTitleEdgeInsets. I hadn't seen that before.
For example, is a button like this achievable?
I've seen questions like this where they go over how to put it before, which is indeed quite easy, but I'm not totally sure how to append it to the end of the text on the button when the text can be anything really. Conceptually, it would be something like having text, and then a UIButton say 10pt to the right of it.
Would the best way to do this simply be a UIView with a UILabel and a UIImageView inside it, with a tap gesture recognizer attached?
A quick sample :
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *img = [UIImage imageNamed:#"Arrow.png"];
[button setTitle:#"A Button" forState:UIControlStateNormal];
[button setImage:img forState:UIControlStateNormal];
[button sizeToFit];
CGRect imageRect = [button imageRectForContentRect:button.bounds];
CGRect titleRect = [button titleRectForContentRect:button.bounds];
UIEdgeInsets imageInset = UIEdgeInsetsZero;
UIEdgeInsets titleInset = UIEdgeInsetsZero;
titleInset.left = -2 * imageRect.size.width;
imageInset.left = titleRect.size.width;
button.titleEdgeInsets = titleInset;
button.imageEdgeInsets = imageInset;
[self.view addSubview:button];
CGFloat prevHeight = button.frame.size.height;
UIButton *anotherButton = [UIButton buttonWithType:UIButtonTypeCustom];
[anotherButton setTitle:#"Another Button" forState:UIControlStateNormal];
[anotherButton setImage:img forState:UIControlStateNormal];
[anotherButton sizeToFit];
imageRect = [anotherButton imageRectForContentRect:anotherButton.bounds];
titleRect = [anotherButton titleRectForContentRect:anotherButton.bounds];
imageInset = UIEdgeInsetsZero;
titleInset = UIEdgeInsetsZero;
titleInset.left = -2 * imageRect.size.width;
imageInset.left = titleRect.size.width;
anotherButton.titleEdgeInsets = titleInset;
anotherButton.imageEdgeInsets = imageInset;
CGRect frame = anotherButton.frame;
frame.origin.y += prevHeight + 4;
[anotherButton setFrame:frame];
[self.view addSubview:anotherButton];
}
You just need to adjust buttons size and insets, if you want to add space between title and image.
You could also just have a UILabel and a UIImageView and an invisible UIButton on top of them.
Or as you said, a UIView with you custom content and a gesture recognizer. In that case however it might be more difficult to achieve the same behavior as a regular button (no highlighting, you can't move your finger before letting go, etc.)
Also, UIButton is a subclass of UIView. This means, you can easily add additional subviews (such as an UIImageView) inside the UIButton.
You could use an empty UIButton and put a UILabel and a UIImageView into it. And use Auto Layout to position them inside the button.
Just create UIButton
UIImage *arrowDownImage = [UIImage imageNamed:#"arrowDown.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:arrowDownImage forState:UIControlStateNormal];
[button setTitle:#"Test" forState:UIControlStateNormal];
// set image and title Inset
[button setImageEdgeInsets:UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)];
[button setTitleEdgeInsets:UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)];
Play with Insets and this will give you exactly what you need.
This is IB example of button, but you can do the same programmatically.
And this is ImageInset
Title Inset
I need a UIButton with image & text. Image should be in the top & text comes under the image both should be clickable.
I see very complicated answers, all of them using code. However, if you are using Interface Builder, there is a very easy way to do this:
Select the button and set a title and an image. Note that if you set the background instead of the image then the image will be resized if it is smaller than the button.
Set the position of both items by changing the edge and insets. You could even control the alignment of both in the Control section.
You could even use the same approach by code, without creating UILabels and UIImages inside as other solutions proposed. Always Keep It Simple!
EDIT: Attached a small example having the 3 things set (title, image and background) with correct insets
I think you are looking for this solution for your problem:
UIButton *_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button setFrame:CGRectMake(0.f, 0.f, 128.f, 128.f)]; // SET the values for your wishes
[_button setCenter:CGPointMake(128.f, 128.f)]; // SET the values for your wishes
[_button setClipsToBounds:false];
[_button setBackgroundImage:[UIImage imageNamed:#"jquery-mobile-icon.png"] forState:UIControlStateNormal]; // SET the image name for your wishes
[_button setTitle:#"Button" forState:UIControlStateNormal];
[_button.titleLabel setFont:[UIFont systemFontOfSize:24.f]];
[_button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // SET the colour for your wishes
[_button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted]; // SET the colour for your wishes
[_button setTitleEdgeInsets:UIEdgeInsetsMake(0.f, 0.f, -110.f, 0.f)]; // SET the values for your wishes
[_button addTarget:self action:#selector(buttonTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside]; // you can ADD the action to the button as well like
...the rest of the customisation of the button is your duty now, and don't forget to add the button to your view.
UPDATE #1 and UPDATE #2
or, if you don't need a dynamic button you could add your button to your view in the Interface Builder and you could set the same values at there as well. it is pretty same, but here is this version as well in one simple picture.
you can also see the final result in the Interface Builder as it is on the screenshot.
Xcode-9 and Xcode-10 Apple done few changes regarding Edge Inset now, you can change it under size-inspector.
Please follow below steps:
Step-1:
Input text and select image which you want to show:
Step-2:
Select button control as per your requirement as shown in below image:
Step-3:
Now go-to size inspector and add value as per your requirement:
swift version:
var button = UIButton()
newGameButton.setTitle("Новая игра", for: .normal)
newGameButton.setImage(UIImage(named: "energi"), for: .normal)
newGameButton.backgroundColor = .blue
newGameButton.imageEdgeInsets.left = -50
In my case, I wanted to add UIImage to the right and UILabel to the left. Maybe I can achieve that by writing code (like the above mentioned), but I prefer not to write code and get it done by using the storyboard as much as possible. So this is how did it:
First, write down something in your label box and select an image that you want to show:
And that will create a button looking like this:
Next, look for Semantic and select Force Right-to-Left (If you don't specify anything, then it will show the image to the left and label to the right like the above image):
Finally, you'll see UIImage to the right and UILabel to the left:
To add space between a label and an image, go to the Size inspector and change those values depending on your requirement:
That's it!
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.imageView.image = [UIImage imageNamed:#"your image name here"];
button.titleLabel.text = #"your text here";
but following code will show label above and image in background
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.background.image = [UIImage imageNamed:#"your image name here"];
button.titleLabel.text = #"your text here";
There is no need to use label and button in same control because UIButton has UILabel and UIimageview properties.
Use this code:
UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(0, 10, 200, 52)];
[sampleButton setTitle:#"Button Title" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];
[sampleButton setBackgroundImage:[[UIImage imageNamed:#"redButton.png"]
stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
[sampleButton addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton]
You should create custom imageview for image and custom label for text and you add to your button as subviews. That's it.
UIButton *yourButton = [UIButton buttonWithType:UIButtonTypeCustom];
yourButton.backgroundColor = [UIColor greenColor];
yourButton.frame = CGRectMake(140, 40, 175, 30);
[yourButton addTarget:self action:#selector(yourButtonSelected:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:yourButton];
UIImageView *imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, yourButton.frame.size.width, yourButton.frame.size.height/2)];
imageView1.image =[UIImage imageNamed:#"images.jpg"];
[yourButton addSubview:imageView1];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0, yourButton.frame.size.height/2, yourButton.frame.size.width, yourButton.frame.size.height/2)];
label.backgroundColor = [UIColor greenColor];
label.textAlignment= UITextAlignmentCenter;
label.text = #"ButtonTitle";
[yourButton addSubview:label];
For testing purpose, use yourButtonSelected: method
-(void)yourButtonSelected:(id)sender{
NSLog(#"Your Button Selected");
}
I think it will be helpful to you.
Use this code:
UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
button.imageView.frame=CGRectMake(0.0f, 0.0f, 50.0f, 44.0f);///You can replace it with your own dimensions.
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 35.0f, 50.0f, 44.0f)];///You can replace it with your own dimensions.
[button addSubview:label];
I encountered the same problem, and I fix it by creating a new subclass of UIButton and overriding the layoutSubviews: method as below :
-(void)layoutSubviews {
[super layoutSubviews];
// Center image
CGPoint center = self.imageView.center;
center.x = self.frame.size.width/2;
center.y = self.imageView.frame.size.height/2;
self.imageView.center = center;
//Center text
CGRect newFrame = [self titleLabel].frame;
newFrame.origin.x = 0;
newFrame.origin.y = self.imageView.frame.size.height + 5;
newFrame.size.width = self.frame.size.width;
self.titleLabel.frame = newFrame;
self.titleLabel.textAlignment = UITextAlignmentCenter;
}
I think that the Angel García Olloqui's answer is another good solution, if you place all of them manually with interface builder but I'll keep my solution since I don't have to modify the content insets for each of my button.
Make UIImageView and UILabel, and set image and text to both of this....then Place a custom button over imageView and Label....
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"search.png"]];
imageView.frame = CGRectMake(x, y, imageView.frame.size.width, imageView.frame.size.height);
[self.view addSubview:imageView];
UILabel *yourLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, y,a,b)];
yourLabel.text = #"raj";
[self.view addSubview:yourLabel];
UIButton * yourBtn=[UIButton buttonWithType:UIButtonTypeCustom];
[yourBtn setFrame:CGRectMake(x, y,c,d)];
[yourBtn addTarget:self action:#selector(#"Your Action") forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:yourBtn];
It's really simple,just add image to background of you button and give text to titlelabel of button for uicontrolstatenormal.
That's it.
[btn setBackgroundImage:[UIImage imageNamed:#"img.png"] forState:UIControlStateNormal];
[btn setContentVerticalAlignment:UIControlContentVerticalAlignmentBottom];
[btn setTitle:#"Click Me" forState:UIControlStateNormal];