Set background image of UIBarButtonItem programmatically changes its size - ios

I've been able to have a custom UIBarButtonItem with an embedded uibutton through story board. It's the map button.
see parameters on this screenshot, I had to use background property instead of Image.
But when I tried to customize some uibarbuttons programmatically, then the buttons get smaller. I had the same result with the map button when I was using Image property.
Here the code i'm writing for the back button,
UIImage *backButtonImage = [[UIImage imageNamed:#"Retour.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(21, 21, 21, 21)] ;
backButtonImage = [backButtonImage stretchableImageWithLeftCapWidth:0 topCapHeight:0];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
[button setBackgroundImage:backButtonImage forState:UIControlStateNormal];
[button setBackgroundImage:backButtonImage forState:UIControlStateHighlighted];
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithCustomView:button] ;
self.navigationItem.leftBarButtonItem = backBarButton;
I tried with or without resizableImageWithCapInsets, stretchableImageWithLeftCapWidth with the same result below (the back button should have the same size as the map button)
I tried also iOS 5 setBackButtonBackgroundImage methods but the button was not customized at all.

If you don't find an answer to your problem, I can suggest you this function :
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
//UIGraphicsBeginImageContext(newSize);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
It returns an image scaled to the specified size.
So you can resize your image at the desired size and then set it as a background image.

Well the problem was that I had overwritten the Retour#2x.png for retina display with Retour.png -__-'

Related

iOS change UIButton frame to it's image frame weird error

I have a strange error when trying to change UIButton's frame.
I am trying to do the following:
UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
UIImage *image = [UIImage imageNamed:imageName];
btn.frame = CGRectMake(0, 0, image.size.width, image.size.height);
[btn setImage:image forState:UIControlStateNormal];
and I an image editor I see that image size is 35x37, but image.size.width / height gives me 16.
What am I doing wrong?
PS: If I double the image.size.width, then the button's frame seems ok. I thought that both image size and UIView frame are in points.

UIButton changes image created in code when in highlighted state

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];

UISlider setMaximumTrackTintColor in iOS 7.1

[slider setMaximumTrackTintColor: color]
has unexpected results in iOS 7.1 (the slider bar changes its position appearing at top instead of vertical center or disappears completely), while working fine with prior versions.
[slider setMinimumTrackTintColor: color]
does render the expected result.
This question might be related: UISlider setMaximumTrackTintColor,
but no answer so far.
Update:
I get this: instead of:
Update #2:
Using setMaximumTrackImage might work, but the solution I'm looking for is a way to set any random color and not a preexisting image.
Update #3:
This issue is still present in iOS 7.1.1.
Found this workaroud:
Create a 1x1px UIImage from a UIColor on the fly:
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
[color setFill];
UIRectFill(rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
and then
[slider setMaximumTrackImage:image forState:UIControlStateNormal];
Looks like an expensive solution but it gets the job done.
Try this out:
UIImage *sliderLeftTrackImage = [[UIImage imageNamed:#"LeftImage.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
UIImage *sliderRightTrackImage = [[UIImage imageNamed:#"RightImage.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[sliderName setMinimumTrackImage: sliderLeftTrackImage forState: UIControlStateNormal];
[sliderName setMaximumTrackImage: sliderRightTrackImage forState: UIControlStateNormal];
If you want to change thumb image the following code will work:
[sliderName setThumbImage:[UIImage imageNamed:#"ThumbImgName.png"] forState:UIControlStateNormal];
[sliderName setThumbImage:[UIImage imageNamed:#"ThumbImgName.png"] forState:UIControlStateHighlighted];
In same way, you can also use color instead of images.
I've created 2px images with the colour of slider track.
And then I set they as tracking images (here's with thumb image for iPad and iPhone)
UIImage *thumbImage = [UIImage imageNamed:#"slider"];
UIImage *trackImage;
if (isiPad) {
[[UISlider appearance] setThumbImage:thumbImage forState:UIControlStateNormal];
[[UISlider appearance] setThumbImage:thumbImage forState:UIControlStateHighlighted];
trackImage = [UIImage imageNamed:#"menu-bar-ipad"];
}
else {
[[UISlider appearance] setThumbImage:[self imageWithImage:thumbImage scaledToSize:CGSizeMake(27, 27)] forState:UIControlStateNormal];
[[UISlider appearance] setThumbImage:[self imageWithImage:thumbImage scaledToSize:CGSizeMake(27, 27)] forState:UIControlStateHighlighted];
trackImage = [UIImage imageNamed:#"menu-bar"];
}
[[UISlider appearance] setMinimumTrackImage:trackImage forState:UIControlStateNormal];
[[UISlider appearance] setMaximumTrackImage:trackImage forState:UIControlStateNormal];
And that's all. Same solution as msmq I guess. And you can see both ways how to make a large image - two images way and scaling way.
Update
Reported this bug and it's already well known. Hopefully they will fix it soon...
Maybe a little bit late, but - here is the answer
You should read description of setter:
The color used to tint the standard maximum track images. Setting this
property removes any custom maximum track images associated with the
slider.
Also this applicable only for maximum color, because minimum setter just change titntColor:
The color used to tint the standard minimum track images.
This mean that slider use some image for maximum track and if u just set tint color nothing will be changes (nothing can't be tinted).
Solution (thanks to #user623396):
UIImage *currentSliderMaximumImage = self.slider.currentMaximumTrackImage;
CGRect rect = CGRectMake(0, 0, currentSliderMaximumImage.size.width, currentSliderMaximumImage.size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
[[[DynamicUIService service] currentApplicationColor] setFill];
UIRectFill(rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.slider setMaximumTrackImage:image forState:UIControlStateNormal];
As result u will get

No resizing, but positioning when setting backgroundImage of UIButton

I want the button to basically overlap a certain part of the original picture and crop the rest instead of squishing the picture into the button. I can't seem to find a UIContentMode to achieve this.
Try this:
You can have a UIImage after some CGRect inside any UIViews. Just make a CGRect with the part of the UIImageView that contains your original UIImage, and execute the code below:
CGRect newImageFrame = CGRectMake(...); //fill this rect according to the crop area of the imageView
UIGraphicsBeginImageContextWithOptions(newImageFrame, YES, 0);
[editingCell.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Now the newImage will hold the image that you will use as background of your button.
Example:
Assuming your UIImageView has the frame (50,50, 100, 200), you can crop a similar result of your image with something like this: newImageFrame = CGRectMake(50, 130, 100, 40).
Please, let me know if worked or not.
please try this code:
CGRect frame = CGRectMake(10, y, 280, 40);
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = frame;
button.tag=i;
[button setTitle:(NSString *)#"new button" forState:(UIControlState)UIControlStateNormal];
[button addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:[UIImage imageNamed:#"temp.png"] forState:UIControlStateNormal];
[self.view addSubview:button];
i have checked it out.
hope this will help you.

UIButton with resizable Image

Ok guys,
i know i am doing something wrong, but i cannot figure that out. here is the code that will
put the resizable image for the normal button state.
self.loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.loginButton.frame = CGRectMake(0.0, 44.0, 314, 44);
UIImage *image = [[UIImage imageNamed:#"loginbutton_image"] resizableImageWithCapInsets:UIEdgeInsetsMake(0.0,10.0,0.0,10.0)];
[self.loginButton setImage:image forState:UIControlStateNormal];
[self addSubview:self.loginButton];
Here is the image
either the image asset is wrong or the code.
the image is of 21 px width.
the cap inset of 10 & 10 on left right leaves 1Px to resize.
does any one spot what i am doing wrong.
thanks all for stopping by
Arun
you should do it this way:
self.loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.loginButton.frame = CGRectMake(0.0, 44.0, 314, 44);
UIImage *image = [[UIImage imageNamed:#"loginbutton_image"] resizableImageWithCapInsets:UIEdgeInsetsMake(0.0,10.0,0.0,10.0)];
[self.loginButton setBackgroundImage:image forState:UIControlStateNormal];
[self.view addSubview:self.loginButton];
This way you are setting the background image property of the button. The background image is already attached to the button view, so no need to addSubview.
try
self.loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.loginButton.frame = CGRectMake(0.0, 44.0, 314, 44);
UIImage *image = [[UIImage imageNamed:#"loginbutton_image"] stretchableImageWithLeftCapWidth:10 topCapHeight:10]; //assuming the height is 44
[self.loginButton setImage:image forState:UIControlStateNormal];
[self addSubview:self.loginButton];

Resources