UIButton with title and image, system selected background doesn't include image - ios

I've got a UIButton of type .system that I am creating programmatically with Swift 4. It has a title and an image, and I'm toggling isSelected on and off on touch. When I toggle it on, there is a lovely coloured background added around the title of the image, but it doesn't extend far enough to include the image. These pictures explain far better than I can:
Is there any way to get that background to extend further over so the icon is a part of it? I don't mind changing the colour of the icon manually, but everything I've tried (titleEdgeInsets, contentEdgeInsets) has just moved the title and background around without actually extending it.
I would prefer to keep the button a .system button rather than a .custom one, and I like that the frame of the button (and therefore the touch area) is larger than that coloured background because it makes it easier to touch, I imagine if I was setting a solid colour backgroundImage to emulate the effect I would have to decrease the touch area to match, which I don't want.
Any help would be most appreciated! Thanks in advance!
Edit: I've added an image with button.layer.borderWidth = 1 to show the actual frame of the button, and how it differs from the isSelected background which appears around the title. (The gray is because it's in a grouped tableView)

The short answer is a .system button really only expects either an image or a title, not both. (See this for a more comprehensive matrix highlighting your issue)
There isn't really anything special about the .system button for your case, though. Create a .custom button and round button.layer.cornerRadius to get the corner effect.

If you use SF symbols, you can make the image part of the titleLabel:
let attachment = NSTextAttachment()
attachment.image = UIImage(systemName: "checkmark.circle")
let imageString = NSMutableAttributedString(attachment: attachment)
let textString = NSAttributedString(string: "Please try again")
imageString.append(textString)
Then set imageString to UIButton.attributedTitle.
https://www.hackingwithswift.com/articles/237/complete-guide-to-sf-symbols
Haven't tested with custom images.

Related

Image in Button for Xcode is showing only tint color on old version [duplicate]

So, I'm a relatively new coder and understand this may be a real simple fix but I can't seem to find how anywhere, just that people know it happens. It is also possible I've misunderstood some other core idea and that is why I can't seem to fix.
I've set up a UIKit button in my storyboard, added both an IBAction and IBOutlet for this button in my script (class? whatever the individual .swift files are called within a project), set the IBO to inherit from UIButton, all in the ViewController class. In the viewDidLoad function I have
button.setImage(UIImage (named: "logo"), for: .normal)
and another line of coder pertaining to a UILabel (everything is fine there). Below the viewDidLoad function I have an array and then the IBA with a little bit of code that shuffles the array and spits out 0 indexed spot onto the screen.
I've been trying to fix this for a few days now and assuming I've understood everything I've read, I've learned that UIImages are immutable (can't be changed) so that tells me that I need to fix this when declaring it in viewDidLoad. I've also learned that it being blue is default in the current swift/xcode state, and that it is a render mode issue, just turning that off will fix the problem. I can't for the life of me connect the last few dots and figure out how to actually tell Xcode to simply use the image I've provided it.
I'm looking for a code solution of course, but the knowledge of why it will work and any corrections/clarifications to what I think I've learned will be even more appreciated so I can help myself more in the future.
Thank you in advance.
-Cyre
Since you haven't specified, I'm assuming the button's "Type" is set to "System" in the storyboard (the default button type when you drag out a new UIButton in storyboards).
By default, system buttons take any image set on it and apply a template rendering mode to it, which makes the image render all non-transparent pixels as a flat color (e.g. the tint color of the button in this case, which is by default the system blue color that you're seeing).
UIImages by default have a renderingMode of automatic, which means the actual effective rendering mode the image takes on is determined by whatever is using the image (in this case, the UIButton).
You can, however, instantiate a UIImage with a renderingMode of alwaysOriginal so that it never is treated as a template image. There are a couple of ways to do this.
1. Programmatically
You can create a new image object with a new rendering mode in code by taking the image you're already creating:
UIImage(named: "logo")
and calling withRenderingMode(_:) on it to return to you a new UIImage object that you then set on your button:
let logoImage = UIImage(named: "logo")
let logoImageAlwaysOriginal = logoImage?.withRenderingMode(.alwaysOriginal)
button.setImage(logoImageAlwaysOriginal, for: .normal)
2. Asset Catalog
An easier way than going the programmatic route above is to just change the image's default rendering type in your asset catalog. Click on the image you want to change in your asset catalog ("logo" in this case), then go to the Attributes Inspector (keyboard shortcut: option+command+4), and change the "Render As" attribute to "Original Image". Now, whenever you use or get this image from the asset catalog (either in your storyboards or in code), the image will have the rendering mode of .alwaysOriginal.
You can either do any of the above options and keep the system button type, OR you can just change your button's type to "Custom" in the storyboard, as custom buttons do not apply a template rendering mode to their images by default. However, you lose some nice things when not using the system button type, like the text color no longer is taken from the button's tint color, and the button doesn't have a nice fade animation when unpressed.

UISearchBar clear button colour change

I've spent a lot of time in searching for a solution but couldn't find any which works and is efficient. As I understand we can't change tint colour of clear button as this property isn't available? The other solution is to change clear button image all together.
https://stackoverflow.com/a/50386999/10733471 this solution comes to the closest but problem with this is that it doesn't show clear button very first time you launch app and enter into search bar to type.
Can anyone suggest a working & efficient solution which doesn't involve using a new image? I'm looking for a solution which takes the default clear button image and reuses it after changing it's colour.
Add the following code to change the color of clear button in Search Bar
let imgClear = UIImage(named: "cross")
searchbar.setImage(imgClear, for: .clear, state: .normal)
This code is working on first time also I have checked in sample project it is working perfectly

An UIBarButtonItem is colored with tint color. Can I get this displayed as it is?

The image below is the original one I want to display:
And I also put the following statement.
leftBtn.image = UIImage(named: "logo")
However, the image is displayes like the following one. I set the tint color as that dark grey.
Referencing this website disable tint on custom uibarbuttonitem images, I put this statement but it didn't make any change.
leftBtn.image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
Is there any other way to make the image shown as I want? Any advice would be appreciated!
You should try this
leftBtn.image = UIImage(named: "logo").imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
That statement doesn't do anything. It returns the image but doesn't use it anywhere. You need to call the setImage method on your leftBtn to actually set the image.

Getting rid of imageView tint on UIButton in UITableViewCell

I have several buttons in my app that utilize images that are pictures.
For the buttons set in Interface Builder, I set the image in attributes inspector. It displays without a tint, as I desire. I checked the method used to set the image in interface builder is UIButton setImage:forState:
Now, if I try to do set the image of the button in cellForRowAtIndexPath in a UITableViewController, there's a tint over the image.
// This puts a tint over the button
customCell.myButton.setImage(buttonImage, forState: .Normal)
As a workaround, I threw an UIImageView behind the button, but when I animate the button the imageView doesn't move, which I find annoying.
I've also tried this:
// This results in a blank image on the button
customCell.myButton.imageView?.contentMode = .ScaleAspectFit
customCell.myButton.imageView?.image = buttonImage
If anyone's got suggestions re: what I'm doing wrong, I welcome your input.
It turns out imageWithRenderingMode solves the problem.
Creates and returns a new image object with the specified rendering mode.
A new image object with the specified rendering mode.
I needed to use the AlwaysOriginal case:
Always draw the original image, without treating it as a template.
let buttonImage = UIImage(named: buttonImageName)?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)

How to add a background image for TextField in cocos2d-x f

I want to add background image for TextField in cocos2d-x for .I surfed all over the internet and could'nt find a viable answer.Is it possible?.If not.Is there an alternative way.Below is the code.
userName = TextField::create("","fonts/Marker Felt.ttf",20);
userName ->ignoreContentAdaptWithSize(false);
userName->setPosition(Point((visibleSize.width/2)+origin.x,(visibleSize.height/2)+origin.y+90));
userName ->setContentSize(Size(240, 160));
userName ->setTextHorizontalAlignment(TextHAlignment::CENTER);
userName ->setTextVerticalAlignment(TextVAlignment::CENTER);
userName ->setPlaceHolder("User Name");
userName ->addEventListener(CC_CALLBACK_2(Login::textFieldEvent, this));
this->addChild(userName);
Text fields in cocos2d have no background property so you have to approach the problem another way. I suggest that you add the background as an ImageView & then add the TextField on top of it (as a child maybe?) and even wrap the two in a class if you intend to use it in more than one place.
You can not set background image for TextField directly, however you can set background color property for TextField and color as background image pattern.
username.backgroundColor = UIColor(patternImage: UIImage(named: "background.png"))
(You can also use separate ImageView but you will also need background image same size as textfield. Otherwise it will not fit well as background(like Stretched image).)

Resources