I want to increase an image button's touch area, and as I searched, I found a way to use contentsCenter property of CALayer.
https://developer.apple.com/documentation/quartzcore/calayer/1410740-contentscenter
The example of the document above shows an image centered inside the layer that can be resized as the size of layer changes, while maintaining the ratio defined in contentsCenter property.
But when I used contentsCenter property, it just stretches the image's center - (0.5, 0.5).
So I added contentsGravity property to .center, but it results in contentsCenter property not working.
button.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
button.center = view.center
button.backgroundColor = .clear
let image = UIImage(named: "profileImage")
button.layer.contents = image?.cgImage
button.layer.contentsCenter = CGRect(x: 0.25, y: 0.25, width: 0.5, height: 0.5)
button.layer.contentsGravity = .center
//button.layer.contentsScale = image?.scale
button.layer.borderColor = UIColor.black.cgColor
button.layer.borderWidth = 2
button.layer.cornerRadius = 5
button.layer.masksToBounds = true
How can I make the image center inside a button with insets maintaining ratio?
You can increase the UIButton Size using the below Code
button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
I am using the default UIImage property of the UIButton to set the back image . I have successfully done it but it seems that the image is appearing small. How to increase the size of the image in UIButton?
let viewForNavigation = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 40))
viewForNavigation.backgroundColor = UIColor.clear
let backbutton = UIButton(frame: CGRect(x: 0, y: 8, width: 320, height: 20))
backbutton.setImage(UIImage(named: "back_button"), for: UIControlState.normal)
backbutton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right:10)
backbutton.contentHorizontalAlignment = .left
backbutton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
backbutton.titleLabel!.font = UIFont().robotoMedium(withFontSize: 20)
backbutton.setTitle(title, for: .normal)
backbutton.setTitleColor(UIColor.black, for: UIControlState.normal)
backbutton.addTarget(self, action: #selector(exitViewController), for: UIControlEvents.touchUpInside)
viewForNavigation.addSubview(backbutton)
let rightBarButton = UIBarButtonItem(customView: viewForNavigation)
self.navigationItem.leftBarButtonItem = rightBarButton
I think you have choose wrong size back button image, please use below image for back button:
Output
I'm trying to change the selection area of a UIBarButtonItem within the navigation controller. Basically I'm trying to change the allowable area that will make that UIBarButtonItem selectable. Right now, the size of my UIBarButtonItem is 40x40, but I can easily select it even if my finger is not touching the button at all.
Here's to illustrate what I mean:
The green represents the size of the UIBarButtonItem. The red represents the allowable area that makes the UIBarButtonItem selectable.
How can I change the width of the red area?
Here's a snippet of code if helpful:
changeMuscleMap = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40) )
changeMuscleMap.setImage(UIImage(named: "change"), forState: .Normal)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: changeMuscleMap)
Thanks!
If you want larger click area than required, try the below code, then making a UIBarButtonItem With custom button:
#implementation CustomButton
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
UIEdgeInsets extendTouchInsets = UIEdgeInsetsMake(20, 0, 20, 0);
CGRect bounds = self.bounds;
bounds.origin.x -= extendTouchInsets.left;
bounds.origin.y -= extendTouchInsets.top;
bounds.size.width += extendTouchInsets.left + extendTouchInsets.right;
bounds.size.height += extendTouchInsets.top + extendTouchInsets.bottom;
return CGRectContainsPoint(bounds, point);
}
#end
You can use the following code to increase or decrease UIBarButtonItem button width.
changeMuscleMap = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 40) )
changeMuscleMap.setImage(UIImage(named: "change"), forState: .Normal)
changeMuscleMap.contentHorizontalAlignment = .left
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: changeMuscleMap)
It can be achieved by making a UIBarButtonItem with custom item as UIImageView instead of UIButton. Try the below code. I hope this will solve it now.
changeMuscleMap = UIImageView(image:UIImage(named: "change"))
imageView.frame = CGRectMake(0, 0, 40, 40)
let leftBarBtn = UIBarButtonItem(customView: imageView)
self.navigationItem.leftBarButtonItem = leftBarBtn
I was able to achieve what I wanted by using #Damien Romito's provided answer here:
UINavigationBar UIBarButtonItems much larger click area than required
Updated for Swift 3.0:
let buttonContainer: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 27, height: 30) )
let barButton: UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30) )
buttonContainer.addSubview(barButton)
barButton = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
barButton(#imageLiteral(resourceName: "image"), for: UIControlState.normal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: buttonContainer)
barButton(self, action: #selector(ViewController.doSomething), for: UIControlEvents.touchUpInside)
I have an UIButton and an UIView where i want to remove bottom border for the button and top border for the view. The image below show an UIButton. When I press this UIButton the UIView will be added as subview (like a dropdown menu), But I want the button and the view merge with each other so it will look like on "box".
I know how to set border width and color:
self.layer.borderWidth = 1
self.layer.borderColor = UIColor(CGColor: "#616366".CGColor).CGColor
But I don't know if it is possible to remove on border line. Hope you guys can help - Thank you
The easiest way is going to be to change your layout a little bit so that rather than adding the UIView as a subview of the UIButton you add them both as siblings to a container view, and draw the border on the container view.
Kind of like this:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
button.setTitle("Button", forState: .Normal)
button.titleLabel?.textColor = UIColor.blackColor()
let container = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
container.addSubview(button)
container.frame = button.frame
container.backgroundColor = UIColor.whiteColor()
container.layer.borderWidth = 5
container.layer.borderColor = UIColor.blackColor().CGColor
let added = UIView(frame:CGRect(x: 0, y: 44, width: 100, height: 200))
added.backgroundColor = UIColor.blueColor()
container.addSubview(added)
container.frame.size.height += added.frame.size.height
XCPlaygroundPage.currentPage.liveView = container
How can I adjust the image size of the UIButton? I am setting the image like this:
[myLikesButton setImage:[UIImage imageNamed:#"icon-heart.png"] forState:UIControlStateNormal];
However this fills up the image to the full button, how do I make the image smaller?
Historic note:
For this now 10+ yr old question, you now typically just set the point size using setPreferredSymbolConfiguration
If I understand correctly what you're trying to do, you need to play with the buttons image edge inset. Something like:
myLikesButton.imageEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30)
Tim's answer is correct, however I wanted to add another suggestion, because in my case there was a simpler solution altogether.
I was looking to set the UIButton image insets because I didn't realize that I could set the content mode on the button's UIImageView, which would have prevented the need to use UIEdgeInsets and hard-coded values altogether. Simply access the underlying imageview on the button and set the content mode:
myButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
See UIButton doesn't listen to content mode setting?
Swift 3
myButton.imageView?.contentMode = .scaleAspectFit
Swift 3:
button.setImage(UIImage(named: "checkmark_white"), for: .normal)
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)
Here is the other solution to scale an imageView of UIButton.
button.imageView?.layer.transform = CATransform3DMakeScale(0.8, 0.8, 0.8)
You can also do that from inteface builder like this.
I think it's helpful.
If your image is too large (and you can't/don't want to just made the image smaller), a combination of the first two answers works great.
addButton.imageView?.contentMode = .scaleAspectFit
addButton.imageEdgeInsets = UIEdgeInsetsMake(15.0, 15.0, 15.0, 5.0)
Unless you get the image insets just right, the image will be skewed without changing the contentMode.
you can use imageEdgeInsets property
The inset or outset margins for the rectangle around the button’s image.
[self.btn setImageEdgeInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
A positive value shrinks, or insets, that edge—moving. A negative value expands, or outsets, that edge.
Heres the Swift version:
myButton.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
Swift 4
You would need to use these two lines of code, in this specific order. All you need is to change the top and bottom value of the edge insets.
addButton.imageView?.contentMode = .scaleAspectFit
addButton.imageEdgeInsets = UIEdgeInsetsMake(10.0, 0.0, 10.0, 0.0)
Insetting the image works for me, but I also needed the button Type to be Custom and the button Style to be Default. The defaults for a button added in Xcode 13 are System for Type and Plain for Style.
self.imageEdgeInsets = UIEdgeInsets(top: 3.0, left: 3.0, bottom: 3.0, right: 3.0)
If you are using symbolic images for the button, then this solution is better:
button.setPreferredSymbolConfiguration(UIImage.SymbolConfiguration(pointSize: 48), forImageIn: .normal)
With the help of Tim C's answer, I was able to create an extension on UIButton using Swift that allows you to specify the image frame by using the .setImage() function with an extra frame parameter
extension UIButton{
func setImage(image: UIImage?, inFrame frame: CGRect?, forState state: UIControlState){
self.setImage(image, forState: state)
if let frame = frame{
self.imageEdgeInsets = UIEdgeInsets(
top: frame.minY - self.frame.minY,
left: frame.minX - self.frame.minX,
bottom: self.frame.maxY - frame.maxY,
right: self.frame.maxX - frame.maxX
)
}
}
}
Using this, if you wanted to set the frame of a UIButton to CGRectMake(0, 0, 64, 64), and set the image of it to myImage with a frame of CGRectMake(8, 8, 48, 48), you could use
let button: UIButton = UIButton(frame: CGRectMake(0, 0, 64, 64))
button.setImage(
myImage,
inFrame: CGRectMake(8, 8, 48, 48),
forState: UIControlState.Normal
)
When changing icon size with
UIEdgeInsetsMake(top, left, bottom, right), keep in mind button dimensions and the ability of UIEdgeInsetsMake to work with negative values as if they are positive.
Example: Two buttons with height 100 and aspect 1:1.
left.imageEdgeInsets = UIEdgeInsetsMake(40, 0, 40, 0)
right.imageEdgeInsets = UIEdgeInsetsMake(40, 0, 40, 0)
left.imageEdgeInsets = UIEdgeInsetsMake(40, 0, 40, 0)
right.imageEdgeInsets = UIEdgeInsetsMake(45, 0, 45, 0)
left.imageEdgeInsets = UIEdgeInsetsMake(40, 0, 40, 0)
right.imageEdgeInsets = UIEdgeInsetsMake(60, 0, 60, 0)
Examples 1 and 3 are identical since ABS(100 - (40 + 40)) = ABS(100 - (60 + 60))
Updated for Swift > 5
set the size:
button.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
set margins:
button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
One approach is to resize the UIImage in code like the following. Note: this code only scales by height, but you can easily adjust the function to scale by width as well.
let targetHeight = CGFloat(28)
let newImage = resizeImage(image: UIImage(named: "Image.png")!, targetHeight: targetHeight)
button.setImage(newImage, for: .normal)
fileprivate func resizeImage(image: UIImage, targetHeight: CGFloat) -> UIImage {
// Get current image size
let size = image.size
// Compute scaled, new size
let heightRatio = targetHeight / size.height
let newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Create new image
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// Return new image
return newImage!
}
Swift 3
I set myButton width and height to 40 and my padding from EdgeInsetsMake is 15 all sides. I suggest to add a background color to your button to see the actual padding.
myButton.backgroundColor = UIColor.gray // sample color to check padding
myButton.imageView?.contentMode = .scaleAspectFit
myButton.imageEdgeInsets = UIEdgeInsetsMake(15, 15, 15, 15)
Updated for Swift 3
yourButtonName.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)
If you don't want to play around with image insets and you are using auto layout (which I assume you do), another solution is to add size constraints to the image view. Make sure the constraints have a priority of 999, otherwise auto layout will complain.
guard let imageView = button.imageView else { return }
let size = CGSize(width: 20, height: 20)
let sizeConstraints = [
imageView.widthAnchor.constraint(equalToConstant: size.width),
imageView.heightAnchor.constraint(equalToConstant: size.height)
]
imageView.translatesAutoresizingMaskIntoConstraints = false
sizeConstraints.forEach { $0.priority = UILayoutPriority(rawValue: priority) }
NSLayoutConstraint.activate(sizeConstraints)
imageView.contentMode = .scaleAspectFit
i think, your image size is also same as button size then you put image in background of the button like :
[myLikesButton setBackgroundImage:[UIImage imageNamed:#"icon-heart.png"] forState:UIControlStateNormal];
you mast have same size of image and button.i hope you understand my point.