I am having an issue with iOS 7.
The code
[searchBar setImage:[UIImage imageNamed:#"icon_search"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
brings different icon sizes on iOS 6 and iOS 7.
The image size is 29x29 and 58x58#2x and under iOS 6 it's displayed properly, but in iOS 7 it's twice or even more times smaller.
What could be the issue? Thanks!
this seems to work for me:
UIImage* image = [UIImage imageNamed:#"icon_search"];
[[UIImageView appearanceWhenContainedIn:[UISearchBar class], nil] setBounds:CGRectMake(0, 0, image.size.width, image.size.height)];
To customize UISearchBarIconSearch you need the following code:
[yourSearchBar setImage:[UIImage imageNamed: #"yourImage.png"]
forSearchBarIcon:UISearchBarIconSearch
state:UIControlStateNormal];
To properly change the icon the resolution image must be exactly: 14x14, 28x28 for #2x and 42x42 for #3x.
I hope this helps :)
After facing some problems with UISearchBar in iOS 7, I decided to switch to UITextField due to the placeholder text alignment.
But I still managed to get it work by setting the image for UISearchBar and it's textfield.
UITextField *textfieldField = [searchBar valueForKey:#"_searchField"];
[searchBar setImage:[UIImage imageNamed:#"icon_search"]
forSearchBarIcon:UISearchBarIconSearch
state:UIControlStateNormal];
UIImage *whatSearchImage = [UIImage imageNamed:#"icon_search.png"];
UIImageView *whatSearchView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 29, 29)];
whatSearchView.image = whatSearchImage;
textfield.leftViewMode = UITextFieldViewModeAlways;
textfield.leftView = whatSearchView;
Funny thing, if you don't set the image for the UISearchBarIcon it will use the default one from Apple but make it big.
I would also like to see if someone has found a better solution for this.
I had the same problem, then I made size for search icon smaller and everything is ok now.
Play with icon size.
E.g. I changed size of retina image from 38x38 to 30x30, and now it works perfect. Probably iOS checks size and if it is not proper it uses instead of retina non-retina image
Related
I am creating a tvOS app and I want to use parallax images on a couple of buttons. From the docs:
To incorporate parallax images in your app:
Create a UIImage object.
You load the image differently depending on whether the image is included in your app bundle or whether you have downloaded the
image.
Bundle—Load images using imageNamed:.
Downloaded file—Load images using imageWithContentsOfFile:.
Create a new UIImageView object using the loaded images.
If the UIImageView is part of another view, set adjustsImageWhenAncestorFocused to YES on the UIImageView.
I know it says UIImageView there, but I was hoping to make the same effect happen on a UIButton, like the home screen app icons.
I've created the artwork, made a stack in the asset catalog, and loaded the image with imageNamed:, but the UIButton does not behave like a parallax image. It does not sway around like the home-screen icons do. It just looks like a flat image.
Is there something else I have to enable in order for the UIButton to behave like the home screen app icons?
UIButton* quitGame = [[UIButton alloc] initWithFrame:rectWithNewX(playAgain.frame, 985)];
[quitGame setImage:[UIImage imageNamed:#"quit.lsr"] forState:UIControlStateNormal];
[quitGame setAdjustsImageWhenHighlighted:YES];
fadeIn(quitGame, self.view, 0.5);
As of right now, this is not possible with just UIButtons, however, I did find a workaround.
Instead, create a UIImageView that will fill the size of the UIButton and make it a subview of the UIButton. Then call the adjustsImageWhenAncestorFocused: and set it to true. Voila!
UIButton* playAgain = [[UIButton alloc] initWithFrame:CGRectMake(centerX(650, self.view), sh() - 250, 300, 180)];
[playAgain setAdjustsImageWhenHighlighted:YES];
[playAgain addTarget:self action:#selector(playAgain) forControlEvents:UIControlEventPrimaryActionTriggered];
fadeIn(playAgain, self.view, 0.5);
UIImageView* playAgainIGV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 180)];
[playAgainIGV setImage:[UIImage imageNamed:#"playagain.lsr"]];
[playAgainIGV setAdjustsImageWhenAncestorFocused:YES];
[playAgain addSubview:playAgainIGV];
I've had issues when setting files or precompiled LSRs.
Creating the LSR in XCode Asset Catalogue through Asset Catalogue -> New Apple TV Image Stack and dragging in the PNGs, then setting the image either through Interface Builder or through this works:
-(void) setLsr:(UIButton *)button lsrNamed:(NSString *)lsr {
[button setAdjustsImageWhenHighlighted:YES];
UIImageView *biv = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, button.frame.size.width, button.frame.size.height)];
[biv setImage:[UIImage imageNamed:lsr]];
[biv setAdjustsImageWhenAncestorFocused:YES];
[button addSubview:biv];
}
Regarding the answer of david I made a simple Swift method to create a parallax effect button:
func createParallaxButton(button: UIButton, imageNamed: String) {
button.adjustsImageWhenHighlighted = true
let buttonBg = UIImageView(image: UIImage(named: imageNamed))
buttonBg.adjustsImageWhenAncestorFocused = true
buttonBg.frame = button.bounds
button.addSubview(buttonBg)
}
createParallaxButton(myButton, imageNamed: "myButtonimage.lsr")
I used this code to use a custom image as the back button in the whole app.
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:#"back"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:#"back"]];
The image dimensions are 30 x 30.
The code adds the image as the back button but the position is not the correct, as you can see in the following image:
Any ideas on how to properly position the image without modifying its dimensions (at least the visual part of the image (circle + arrow))?
EDIT:
I don't want to use a custom back button because that forces me to disable the swipe/back-gesture in iOS7
EDIT
I think I might have found the trick (in iOS 7 Design Resource -- UIKit User Interface Catalog.)
Under Bar Button Items
Note that a bar button image will be automatically rendered as a template image within a navigation bar, unless you explicitly set its rendering mode to UIImageRenderingModeAlwaysOriginal. For more information, see Template Images.
Under Template Images they have some code to specify the UIImageRenderingMode.
UIImage *myImage = [UIImage imageNamed:#"back"];
UIImage *backButtonImage = [myImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// now use the new backButtomImage
[[UINavigationBar appearance] setBackIndicatorImage:backButtonImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backButtonImage];
Try creating the UIImage with alignment insets and then set the Back Indicator image.
UIEdgeInsets insets = UIEdgeInsetsMake(10, 0, 0, 0); // or (0, 0, -10.0, 0)
UIImage *alignedImage = [[UIImage imageNamed:#"back"] imageWithAlignmentRectInsets:insets];
[[UINavigationBar appearance] setBackIndicatorImage:alignedImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:alignedImage];
You might also try adjusting the position of the UINavigationBar title text
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics];
Well just follow one of the suggestions to fix the layout and lose the iOS 7 "back gesture", and then fix it with a UIScreenEdgePanGestureRecognizer!
A UIScreenEdgePanGestureRecognizer looks for panning (dragging) gestures that start near an edge of the screen. The system uses screen edge gestures in some cases to initiate view controller transitions. You can use this class to replicate the same gesture behavior for your own actions.
PLEASE SEE EDIT BELOW!!!
I created a custom back button in iOS7 not too long ago. Mine has an arrow and the word back on it. I do think pawan's suggestion is a good start. To create the back button with your custom image you can use,
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonClicked)];
[backButton setBackgroundImage:finalImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[backButton setTitlePositionAdjustment:UIOffsetMake(-20, 0) forBarMetrics:UIBarMetricsDefault];
self.navigationItem.leftBarButtonItem = backButton;
My image finalImage is a composite of two different images, but you can just use your "back" image. But I think that is where the problem lies. My image was a composite, you might want to make a composite as well, but put a clear space above your back icon. I placed a clear space to the right of my icon to adjust it's spacing. Here is the code,
UIImage *arrow = [UIImage imageNamed:#"back.png"];
UIImage *wordSpace = [UIImage imageNamed:#"whiteSpace.png"];
CGSize size = CGSizeMake(arrow.size.width + wordSpace.size.width, arrow.size.height);
UIGraphicsBeginImageContext(size);
[arrow drawInRect:CGRectMake(0, 0, arrow.size.width, size.height)];
[wordSpace drawInRect:CGRectMake(arrow.size.width, 0, wordSpace.size.width, wordSpace.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
The Image wordSpace is a clear png that I made in photoshop so my new back button image was not stretched. You might want to place a clear png on top, to push the icon down a little. Make the size.height of it in photoshop for what you think the adjustment should be. You might need to futz with this a bit. And make sure to change up the CGSize so that it fits your icon and the clear space.
My word back was a bit off, so I looked at
[backButton setTitlePositionAdjustment:UIOffsetMake(-20, 0) forBarMetrics:UIBarMetricsDefault];
I had to play around with that line a bit to make it look as good as possible but it finally gave me what I wanted with the -20. I even adjusted the second variable which is 0 in mine, this moved the actual icon around. -5 put the icon down way to far, but its another option from the clear png.
Now to deal with the fact that you want it to be an actual back button. Look at the first line of code I posted. The action on the button is #selector(backButtonClicked). So all you need to do is make that method and you should be good to go!
- (void)backButtonClicked
{
NSLog(#"going back");
[self.navigationController popViewControllerAnimated:YES];
}
Hope this helps a bit.
EDIT*****
I was playing around with my code a little bit and found a better way to move the back icon. I just used a ship's wheel because I didn't have the same one that you did, but it will work the same.
Since you don't really want a title you can create the button with this code,
UIImage *image = [UIImage imageNamed:#"781-ships-wheel.png"];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:#selector(backButtonClicked)];
Just change the 781 stuff with your icon's name. Then you can move it around with the following,
[backButton setImageInsets:UIEdgeInsetsMake(20, 0, -20, 0)];
Take a look at this picture.
This shows the icon down considerably, but I wanted to show you the idea. The numbers for the Edge insets are Top, Left, Bottom, and Right. Don't touch the left and right if you don't need to move it that way, change the top and bottom. Notice however, that if you need to move it down by 20 points like I did, (way too much) you need to offset in the negative for the bottom, or the icon will get compressed. This is what it looks like with all zero's.
So you can pretty much move it where ever you want, but you will still have to set up the #selector(backButtonClicked) to make it work like the real back button.
This is Swift 2 version.
The simplest way is like this. Put this code in AppDelegate.'
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let navigationBarAppearace = UINavigationBar.appearance()
let image = UIImage(named: "back-btn")
navigationBarAppearace.backIndicatorImage = image
navigationBarAppearace.backIndicatorTransitionMaskImage = image
return true
}
if your back button has background colour, it may won't work correctly.
Add your icon to asset folder for each resolution like this:
You can try this
self.navigationItem.leftBarButtonItem.imageInsets = UIEdgeInsetsMake(0, 0, 10, 0);
The problem is that your image is too tall. To prove this, first try this code:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,20), NO, 0);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(6,0,4,20));
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorImage = im;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,20), NO, 0);
UIImage* im2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorTransitionMaskImage = im2;
It looks fine. Now change the 20 to 30 in the two CGSizeMake calls:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,30), NO, 0);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(6,0,4,20));
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorImage = im;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,30), NO, 0);
UIImage* im2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorTransitionMaskImage = im2;
The icon is now too high.
So just make your image 20 pixels tall and all will be well.
UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, -2, 0); // or (2,0,0,0)
UIImage *backArrowImage = [[UIImage imageNamed:#"back"] imageWithAlignmentRectInsets:insets];
[[UINavigationBar appearance] setBackIndicatorImage:backArrowImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backArrowImage];
On iOS 6 SDK I wrote the following lines of code to display an image inside a button:
NSURL *thumbURL2 = [NSURL URLWithString:#"http://example.com/thumbs/2.jpg"];
NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2];
UIImage *thumb2 = [UIImage imageWithData:thumbData2];
[btn2 setImage:thumb2 forState:UIControlStateNormal];
[self.view addSubview:btn2];
But now with Xcode 5 and iOS 7 this doesn't work. The button doesn't contain the image. The button is filled with blue color.
In iOS7 there is new button type called UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), // standard system button
Check your .xib file and change button type to Custom
To do this programmatically, add this line to the viewDidLoad:
[UIButton buttonWithType:UIButtonTypeSystem];
It seems iOS 7 is using the image provided just as an Alpha mask for displaying the button's tint color.
Changing the button type to UIButtonTypeCustom did the trick for me (thanks user716216!).
Setting the image as background doesn't always work if you already have a background image, as was my case.
Swift 3, 4, 5 :
let image = UIImage(named: "my-image")
myButton.setImage(image.withRenderingMode(.alwaysOriginal), for: .normal)
There's a good chance that the image is there and you just can't see it. Try changing the button's type to UIButtonTypeCustom. If that doesn't work, set the button's background color to [UIColor clearColor];
For swift:
let aButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
The issue is the TintColor. By default, iOS throws a blue tint color over every button. You can get around it through 3 ways.
Change the tint color. [button setTintColor:[UIColor blackColor]];
This may color your image in ways you don't want it to.
As most other suggested, set the background image. [button setBackgroundImage:[UIImage...]];
Add an UIImageView to your button.
UIImageView * img = [[UIImageView alloc] initWithImage:[UIImage...]];
[button addSubView:img];
I had the same issue.
On my storyboard I had a button without any image.
I would then assign the image in the code.
IOS 7 came and I got a lot of blue images.
The resolution was simple yet confusing. If I assign any image on the storyboard and then change the image at run time it works fine.
You always must specify a starting image on the storyboard even if you are not going to use it.
This worked for me
[myButton1 setBackgroundImage:[UIImage imageNamed:#"phones.png"] forState:UIControlStateNormal];
Note:Remove front image before doing this.
Old thread, but I wanted to chime in because I just had the same problem. The issue was just that you are calling setImage when you should call setBackgroundImage.
In iOS 13 -- just set the Tint property to White, while keeping the type of the UIButton as Custom
None of the given solutions were working for me. If you do not set an initial image in Storyboard, you can still change the image of the button by using setBackgroundImage.
For your example, only a minor change is needed.
NSURL *thumbURL2 = [NSURL URLWithString:#"http://example.com/thumbs/2.jpg"];
NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2];
UIImage *thumb2 = [UIImage imageWithData:thumbData2];
[btn2 setBackgroundImage:thumb2 forState:UIControlStateNormal];
[self.view addSubview:btn2];
This Problem is called blue color problem of the button in xcode.
When we make button by code the button shows the blue tint color by default.This can be solved byt assigning tint color to black or white accordingly to your cell's color.
The code is :
UIImage *closebtnimg = [UIImage imageNamed:#"icon_uncheck.png"];
UIImage *closebtnimg1 = [UIImage imageNamed:#"icon_checked.png"];
Custombutton *button = [Custombutton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(52, 66, 25, 24)];
[button setBackgroundImage:closebtnimg forState:UIControlStateNormal];
[button setBackgroundImage:closebtnimg1 forState:UIControlStateSelected];
[button setTintColor:[UIColor whiteColor]];
[cell.contentView addSubview:button];
[button addTarget:self action:#selector(changeImage:) forControlEvents:UIControlEventTouchUpInside];
Using Xcode 9.2 none of the above solutions worked for what I was looking for.
I was looking for a solution that will let me set .normal and .selected UIControlState images inside the storyboard for their original rendering mode, but, inside the Swift file, no string literals should exist regarding the image names.
Basically, inside your code you will get the image you set inside your storyboard for .normal state and re-render it as .alwaysOriginal (Same for .selected state), then, you will set that image (which is now rendered as original and won't be affected by the tint) for the relevant state (.normal and .selected) of your UIButton.
Here it is:
// Get your .normal image (you set via your storyboard) and render it as original
let unselectedImage = yourButton.image(for: .normal)?.withRenderingMode(.alwaysOriginal)
// Set your normal image but this time rendered as original
yourButton.setImage(unselectedImage, for: .normal)
// Same for selected state
let selectedImage = yourButton.image(for: .selected)?.withRenderingMode(.alwaysOriginal)
yourButton.setImage(selectedImage, for: .selected)
This way you can set your button image states and if the image name will change, it won't affect your code.
making the tint color as clearcolor for all the four states(Default,Highlighted,selected,disabled) worked for me.
In Swift 4, initialize your UIButton and assign uyour image Data as follows:
let myButton = UIButton(type: .cutsom)
myButton.setImage(UIImage(data:myImageData), for: .normal)
I'm trying to customize the text field of the UISearchBar on iOS, but I'm having issues. Using the following method:
[searchBar setSearchFieldBackgroundImage:searchFieldImage forState:UIControlStateNormal];
gives me the image in the text field, but it is TINY. The image is only 40x15 px dimension, and is used for stretching. I'm creating the image as follows:
UIImage *searchFieldImage = [[UIImage imageNamed:#"input_15x40.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(7, 19, 7, 20)];
However, it seems that this appearance modification doesn't stretch the image - just takes it as is. How can I go about customizing the textfield image of the UISearchBar with a stretchable image?
EDIT
I should say that the bar is stretched horizontally, but it is NOT stretched vertically, and thus is only 15px height.
The only problem that I can see in your code is that you create the var named searchFieldImage and use it as searchField.
This code worked for me:
UIImage *searchFieldImage = [[UIImage imageNamed:#"input_15x40.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(7, 19, 7, 20)];
[searchBar setSearchFieldBackgroundImage:searchFieldImage forState:UIControlStateNormal];
-
Edit:
In the height, the image will not stretch because the height of the image will set the height of the view that wraps it.
let searchTextField = searchBar.valueForKey("_searchField") as? UITextField
searchTextField?.backgroundColor = UIColor.redColor()
I have some images I need to get from the web. Just using data from a URL.
They need to show correctly on Retina Display.
When I get the images from the web, they still look pixelated. I need to set the images' scale to retina display (2.0), but I must be missing something.
Here's what I did so far.
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:#"http://www.msdomains.com/tmp/test.png"];
CGRect labelFrame = CGRectMake(0,0,64,64);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:labelFrame];
imageView.contentScaleFactor = [UIScreen mainScreen].scale;
[imageView setImage:img];
[self addSubview:imageView];
[imageView release];
Try adding ##2x.png at the end of your URL. That wont change the URL, but the image will be recognized as a retina #2x image. It worked for me, but I used this method with SDWebImage.
e.g. using http://www.msdomains.com/tmp/test.png##2x.png.
Your code should work pretty much as-is. I don't know what the original dimensions of your image were, but I'd guess they were 64x64 px. In order to scale down correctly, the original image would need to be 128x128 px.
As a test, the following code correctly displayed my photo in Retina resolution on the Simulator, and on my iPhone 4:
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.seenobjects.org/images/mediumlarge/2006-08-19-native-lilac.jpg"]]];
CGRect labelFrame = CGRectMake(0, 0, 375, 249.5);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:labelFrame];
[imageView setImage:img];
[self.view addSubview:imageView];
Note that the UIImageView is 375x249.5 points, which is half of the original (pixel) dimensions of the photo. Also, setting the contentScaleFactor didn't seem to be necessary.
(As an aside, I can't see that specifying #2x on the URL will help, in this case, as the call to dataWithContentsOfURL: will return an opaque blob of data, with no trace of the filename left. It's that opaque data that's then passed to imageWithData: to load the image.)
when you directly assign the image URL to imageView, it will not take it as retina.
imageView.imageURL = [NSURL URLWithString:#"http://example.com/image.png"];
will not give you a retina image.
So, inspite your image is 200x200 but if your imageView is 100x100 then it will take 100x100 from the downloaded image and show pixelated image on retina devices.
Solution would be to use the image property of imageView instead of imageURL.
imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://example.com/image.png"]]];
This will assign 200x200 image to the imageView of 100x100 and hence the image will not be pixelated.
For retina display, add the same image with the resolution which is exactly the double of the original image. dont forget to add "#2x"at the end of this image name... e.g. "image_header.png" is an image 320x100 then another image with name "image_header#2x.png" (dimension 640x200) will be selected for the retina display automatically by the OS...
hope it helps