How to change the selection area of a UIBarButtonItem? - ios

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)

Related

UIButton ImageView contentmode doesn't work

I just started an app for iOS in Swift, I'm doing the design programmatically (I mean I'm not using storyboard)
I have a UIButton with an image inside, I would like the image to fill the entire button. Right now it just show the image in my button, but smaller than the button, center in top of the button frame.
My code is :
let buttonLocation = UIButton(frame: CGRect(x: 0, y: 0, width: buttonRoundedSize, height: buttonRoundedSize))
buttonLocation.setImage(UIImage(named: "locate_button"), for: .normal)
buttonLocation.backgroundColor = .white
buttonLocation.layer.cornerRadius = frame.width / 2
buttonLocation.myExtension()
Here are the things I've tried (none of theses worked) :
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.autoresizingMask = .flexibleWidth
self.autoresizingMask = .flexibleHeight
self.imageView?.contentMode = .scaleAspectFill
If I just put the contentMode line it doesn't work either. The imageView doesn't return nil i've checked..
Thanks!
Set the contentMode of buttonLocation's imageView as scaleAspectFill or scaleToFill to cover the entire frame of button.
let buttonLocation = UIButton(frame: CGRect(x: 0, y: 0, width: 200, height: 500))
buttonLocation.setImage(UIImage(named: "image"), for: .normal)
buttonLocation.backgroundColor = .gray
buttonLocation.layer.cornerRadius = buttonLocation.frame.width / 2
buttonLocation.imageView?.contentMode = .scaleAspectFill //Here........
Example:
Try using below code and remove other properties which are being set for this button :
let buttonLocation = UIButton(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
buttonLocation.setImage(UIImage(named: "cat"), for: .normal)
buttonLocation.backgroundColor = .white
buttonLocation.layer.cornerRadius = 50
buttonLocation.imageView?.contentMode = .scaleAspectFill
buttonLocation.clipsToBounds = true
self.view.addSubview(buttonLocation)
Here make sure that the image which you are setting in the button is larger than the frame of the button. You can change frame and corner radius values in the above code. I just tried with the above code and getting below output.
You can comment if this is not your expected output.
Hope this helps.
Answer on your question: https://stackoverflow.com/a/26263623/3047318
TLDR: set contentMode in viewDidLoad
you need to use setBackgroundImage property instead of setImage.
buttonLocation.setBackgroundImage(UIImage(named: "locate_button"), for: .normal)
Maybe this can help you:
let buttonLocation = UIButton(type: .custom)
buttonLocation.frame = CGRect(x: 0, y: 0, width: buttonRoundedSize, height: buttonRoundedSize)
buttonLocation.setImage(UIImage(named: "locate_button"), for: .normal)
buttonLocation.imageView?.contentMode = .scaleAspectFill
buttonLocation.contentHorizontalAlignment = .fill
buttonLocation.contentVerticalAlignment = .fill
buttonLocation.backgroundColor = .white
buttonLocation.layer.cornerRadius = frame.width / 2
buttonLocation.clipsToBounds = true
You need to add contentHorizontalAlignment and contentVerticalAlignment properties and don't forget set clipsToBounds to true to see the corner raius effect.

Setting left view to the TextField with its bottom

I want to set the Leftview to the TextField. But I want to align it to the bottom of the Textfield. So that the leftview frame looks align to the TextField actual text. But I am not getting any luck.
here is how I am trying with it.
let btnSelectCountry = UIButton()
btnSelectCountry.setTitle(title, for: UIControlState.normal)
btnSelectCountry.titleEdgeInsets = UIEdgeInsetsMake(0, 0, -10, 0)
btnSelectCountry.backgroundColor = CommonUtils.hexStringToUIColor(hex: "#000000")
btnSelectCountry.frame = CGRect(x: 0, y: CGFloat(0), width: CGFloat(70), height: CGFloat(25))
btnSelectCountry.addTarget(self, action: #selector(self.selectCountryCallingCode), for: .touchUpInside)
etPhoneNum.leftView = btnSelectCountry
etPhoneNum.leftViewMode = .always
etPhoneNum.leftViewRect(forBounds: CGRect(x: 0, y: CGFloat(-100), width: CGFloat(70), height: CGFloat(25)))
But it is showing vertically aligned in the TextField. How can I move LeftView to bottom inside the TextField??
func setTextLeftView(){
txtField.leftView = UIImageView.init(image: image)
txtField.leftView?.frame = CGRect(x: 0, y: 5, width: 20 , height:20)
txtField.leftViewMode = .always
}
try this and if it does't work for you then let me know if would like to solve your problem :)

how to remove padding left UIBarButtonItem?

I would like to use a custom View as UIBarButtonItem left in an UINavigationController, is it possible to remove the left padding here?
Ill alrady tried:
let btn = UIButton()
btn.frame = CGRect(x: -50, y: -50, width: 44, height: 50)
btn.setImage(UIImage(name:"img").withRenderingMode(.alwaysTemplate), for: .normal)
btn.addTarget(self, action: #selector(openSetting), for: .touchUpInside)
let leftButtonBar = UIBarButtonItem(customView: btn)
self.navigationItem.leftBarButtonItems = ( [leftButtonBar , otherBtn ])
how to remove space left setting icon
update. tired this code:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height:
view.backgroundColor = .gray
let btn = UIButton()
btn.frame = CGRect(x: -15, y: 0, width: 44, height: 50)
btn.setImage(UIImage(name:"img").withRenderingMode(.alwaysTemplate), for: .normal)
btn.addTarget(self, action: #selector(DashboardTabBarController.openSetting), for: .touchUpInside)
view.addSubview(btn)
let leftButtonBar = UIBarButtonItem(customView: view)
problem this user when clicked btn setting user
and other problem title navigation not center align
You should have noticed that whatever x value you provide to your custom view i.e, btn, it will always start from the same position because internally navigation bar doesn't count for position provided for that item and it always set the internally defined position as in below image, I set the background color to the custom button for better visuals.
So, the trick here is to put your custom button into another container view as below,
let view = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 50)))
view.backgroundColor = .green
let btn = UIButton(frame: CGRect(x: -10, y: 10 , width: 30, height: 30))
btn.setImage(UIImage(named: "cancelled")?.withRenderingMode(.alwaysTemplate), for: .normal)
btn.addTarget(self, action: #selector(openSetting), for: .touchUpInside)
btn.backgroundColor = .yellow
btn.tintColor = .red
view.addSubview(btn)
let btn2 = UIButton(frame: CGRect(x: 20, y: 10, width: 30, height: 30))
btn2.setImage(UIImage(named: "cancelled")?.withRenderingMode(.alwaysTemplate), for: .normal)
btn2.contentMode = .scaleAspectFit
btn2.tintColor = .yellow
btn2.addTarget(self, action: #selector(openSetting), for: .touchUpInside)
view.addSubview(btn2)
let itemsContainer = UIBarButtonItem(customView: view)
self.navigationItem.leftBarButtonItems = [itemsContainer]
This will result into this,
Now, if you change the x, y, width, height of btn, it will adjust accordingly.
Please try this. It works fine for me. If this code not working properly then I will give you another solution.
let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
let btn = UIButton()
btn.frame = CGRect(x: -15, y: 0, width: 44, height: 50)
btn.setImage(UIImage(name:"img").withRenderingMode(.alwaysTemplate), for: .normal)
btn.addTarget(self, action: #selector(openSetting), for: .touchUpInside)
view.addSubview(btn)
let leftButtonBar = UIBarButtonItem(customView: view)
self.navigationItem.leftBarButtonItems = ( [leftButtonBar])
Please add other button in View and set the width of view accordingy.It may hepls to you.Thank you
You can set imageInsets and set image this is example of left margin to set back image on position of default back button
let rightBtn = UIBarButtonItem(image: UIImage(named: "BackArrow"), style: .done, target: self, action: #selector(actnClose))
rightBtn.imageInsets = UIEdgeInsets(top: 0, left: -12, bottom: 0, right: 0)
self.navigationItem.setLeftBarButton(rightBtn, animated: true)
Set the x value of cRect to zero:
btn.frame = CGRect(x: 0, y: -50, width: 44, height: 50)
The less painful and actually cleanest solution was to hide the left button and just add a subview directly to the navigationBar and customise it's position and size with the good old constraints. Worked like a charm. Haven't tested it in every situation but seems to work fine.

How to create a button and segue from titleView image

Having a problem with customizing the navigationBar. I have changed the titleView text to an image through coding. Now I want the image to be a clickable button with a segue to the starting page (for example a home button to the main viewController). How do I make the titleView image into a button (or item) and how do I create a segue from it. I suppose it has to be done in code since I haven't found any other means of doing it. If you have a solution, please be thorough - I'm a beginner.
Simply add a custom UIView containing UIButton and UIImageView to the titleView of navigationItem.
Example:
override func viewDidLoad()
{
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.width - 80, height: 30))
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(showMainVC), for: .touchUpInside)
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width - 80, height: 30))
imageView.image = UIImage(named: "Image")
let customView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width - 80, height: 30))
customView.addSubview(imageView)
customView.addSubview(button)
self.navigationItem.titleView = customView
}
func showMainVC()
{
//TODO:
}

How to remove specific border on an UIButton and an UIView?

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

Resources