One way to left-align a UIButton's title is to set the contentHorizontalAlignment to .left (or .leading). But this places the title flush with the left edge of the button with no margin. A common way to add some margin is to set the contentEdgeInstets.
But my button extends from once edge of the screen to the other, so I would like the left and right margins to honor the layoutMargins. These margins might change as the view is resized or the device is rotated.
Is there a way to set the button's insets to observe these margins? Or should I create a button from a custom view where I can use my own label and anchor it to the layoutMarginsGuide?
I guess you can manually set the margin of the button using titleEdgeInsets to match the inset of the Cancel Button.
Have a look at the following, the two buttons are exactly the same aside from the origin.y and the titleEdgeInsets:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
view.backgroundColor = .white
let button = UIButton(frame: CGRect(x: 40, y: 40, width: 200, height: 80))
button.setTitle("Some really long title", for: .normal)
button.backgroundColor = .red
button.setTitleColor(.black, for: .normal)
let button2 = UIButton(frame: CGRect(x: 40, y: 160, width: 200, height: 80))
button2.setTitle("Some really long title", for: .normal)
button2.backgroundColor = .red
button2.setTitleColor(.black, for: .normal)
button2.titleEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
view.addSubview(button)
view.addSubview(button2)
It gives the following result:
Hope this helps :)
A subclassed button may work for you...
class RespectSuperviewMarginButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
if let sv = superview {
contentEdgeInsets.left = sv.layoutMargins.left
}
}
}
My current best answer is: no, this is not possible without subclassing.
The subclass implementation I am currently using is simple enough:
class LayoutMarginRespectingButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
contentEdgeInsets = layoutMargins
}
}
Related
I am trying to overlap the button on two or more views. So when I add this on the first view it is not showing on the second view so I want one button must shown on two views.
You can make two views and embed second view to first and then button to second View and can play with its Y axis
class overlapViewcontroller:UIViewController {
private let firstView:UIView = {
let view = UIView(frame: CGRect(x: 10,
y: 100,
width: 350,
height: 50))
view.backgroundColor = .green
return view
}()
private let secondView:UIView = {
let view = UIView(frame: CGRect(x: 10,
y: 10,
width: 330,
height: 30))
view.backgroundColor = .purple
return view
}()
private let button:UIButton = {
let button = UIButton(frame: CGRect(x: 10,
y: -5,
width: 310,
height: 20))
button.setTitle("Button", for: .normal)
button.backgroundColor = .systemOrange
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
view.addSubview(firstView)
firstView.addSubview(secondView)
secondView.addSubview(button)
}
}
Did you try this? You need to add the button to the container subview and add
this line container.bringSubviewToFront(button)
https://www.hackingwithswift.com/example-code/uikit/how-to-bring-a-subview-to-the-front-of-a-uiview
You need either to
add the button as the very last so that it can be the top one on the subviews stack
or to apply the superview.bringSubviewToFront(button)
I use the extension to UIButton and I added it to my UIButton but I still can't see the line.
I'm missing something, please help
extension:
https://gist.github.com/Isuru-Nanayakkara/496d5713e61125bddcf5
my code:
let settingsButton : UIButton = {
let button = UIButton()
button.setTitle("Settings", for: .normal)
button.setTitleColor(.white, for: .normal)
button.addBorder(side: .Bottom, color: .white, width: 100)
return button
}()
I want to get something like this:
Add a UIView that has [x] points height and same width as the button, and its y position is the same as the height of the button.
let frame = CGRect(x: 0, y: button.frame.size.height, width: button.frame.size.width, height: 2)
let borderBottom = UIView(frame: frame)
borderBottom.backgroundColor= UIColor.white
button.addSubview(borderBottom)
Swift 4.2 implemented views programmatically only
I have created a stack view and put four buttons in it but they are just simple buttons without any gray background.
I want to achieve the exact four buttons in my stackview equally centered as like as -
button.contentEdgeInset //Not working
This is what I tried -
let feedbackButton:UIButton = {
let origImage = UIImage(named: "feedback")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.translatesAutoresizingMaskIntoConstraints = false
button.setBackgroundImage(tintedImage, for: UIControl.State.normal)
button.tintColor = .systemPinkColor
button.layer.cornerRadius = 7
button.backgroundColor = UIColor.lightGray.withAlphaComponent(0.5)
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
// button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 50, bottom: 0, right: 50)
// button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 50, bottom: 0, right: 50)
button.clipsToBounds = true
button.addTarget(self, action: #selector(feedbackFaculty), for: .touchUpInside)
return button
}()
Output -
The button's image gets stretched along with insets. button.imageInsets and button.titleInsets not working.
Help me out. Thanks!
The background image doesn't follow the content insets. So this line:
button.setBackgroundImage(tintedImage, for: UIControl.State.normal)
needs to be changed to:
button.setImage(tintedImage, for: .normal)
Also, here's a couple things to note (per Apple's UIButton documentation):
Supply a title string or image; size the button appropriately for your content.
Which implies that you cannot set an image and title at the same time, this might be why you're noticing titleInset and imageInset not playing nicely.
However, if you just set appropriate constraints for the buttons and set insets for the title OR the image you should be able to get the look you want. Also make sure your stack view is configured to use equal spacing for it's distribution.
The imageInset for each button in the image below is (20, 20, 20, 20).
let SearchView = UIView()
SearchView.backgroundColor = UIColor.clear
SearchView.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
let Searchbutton = UIButton(type: .system)
Searchbutton.setImage(UIImage (named: "SEARCH"), for: .normal)
Searchbutton.backgroundColor = .clear
Searchbutton.frame = CGRect(x: -17, y: -20, width: 30, height: 30)
Searchbutton.contentMode = .scaleAspectFit
let WidthConstraint = Searchbutton.widthAnchor.constraint(equalToConstant: 30)
let HeightConstraint = Searchbutton.heightAnchor.constraint(equalToConstant: 30)
WidthConstraint.isActive = true
HeightConstraint.isActive = true
let barButtonItem = UIBarButtonItem(customView: SearchView)
self.navigationItem.rightBarButtonItem = barButtonItem
SearchView.addSubview(Searchbutton)
Searchbutton.addTarget(self, action: #selector(viewanewcontroller(button:)), for: .touchUpInside)
//right search button
After making a button, I wanted to move it little bit to the right. So, i made UI View to move the button inside the view. But, then, after this, the button does not work anymore. Can anyone tell me the solution?
Your code is working fine but need to clarify some points.
Reason Your button not working is below 4 lines
let WidthConstraint = Searchbutton.widthAnchor.constraint(equalToConstant: 30)
let HeightConstraint = Searchbutton.heightAnchor.constraint(equalToConstant: 30)
WidthConstraint.isActive = true
HeightConstraint.isActive = true
As you already set UIButton frame then no need to use of above lines of code.
Yellow color view is your SearchView and green color is your UIButton.
If you use Searchbutton frame like Searchbutton.frame = CGRect(x: -17, y: -20, width: 30, height: 30) then it happens something like below image.
You added UIButton as subview of UIView and when you click on green button which is inside yellow View will work but the area which is outside Yellow area doesn't work.
You need to start UIButton frame from 0,0,30,30
Searchbutton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
or you can directly set UIButton frame same as UIView frame then it looks like below image.
Searchbutton.frame = SearchView.frame
Below is your Working Code.
let SearchView = UIView()
SearchView.backgroundColor = UIColor.clear
SearchView.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
let Searchbutton = UIButton(type: .system)
Searchbutton.setImage(UIImage (named: "SEARCH"), for: .normal)
Searchbutton.backgroundColor = .clear
Searchbutton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
Searchbutton.contentMode = .scaleAspectFit
let barButtonItem = UIBarButtonItem(customView: SearchView)
self.navigationItem.rightBarButtonItem = barButtonItem
SearchView.addSubview(Searchbutton)
Searchbutton.addTarget(self, action: #selector(viewanewcontroller(button:)), for: .touchUpInside)
//right search button
You're doing a lot of unnecessary things here. Firstly, you don't need to put your Button in a container view to put it as the right bar button item.
You also don't need to add constraints to your searchbutton, since you have given it a fixed frame.
let Searchbutton = UIButton(type: .system)
Searchbutton.setImage(UIImage (named: "SEARCH"), for: .normal)
Searchbutton.backgroundColor = .clear
Searchbutton.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
Searchbutton.contentMode = .scaleAspectFit
let barButtonItem = UIBarButtonItem(customView: Searchbutton)
self.navigationItem.rightBarButtonItem = barButtonItem
Searchbutton.addTarget(self, action: #selector(viewanewcontroller(button:)), for: .touchUpInside)
Also as Pratik's comment said, you're meant to use lower camel case. so SearchView should be searchView and SearchButton as searchButton
As for moving it to the right, it seems like that isn't possible anymore without either subclassing the UINavigationBar and changing the implementation, or by making UIViews look exactly like the standard Navigation Bar.
Get rid of the space on the right side of a UINavigationBar
I am having some difficulties creating a bar button that are leaving me pretty stumped. Im using the following code to create a right bar button:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 22, height: 22))
button.setBackgroundImage(UIImage(named: "tune"), for: .normal)
button.addTarget(self, action:#selector(viewController.settingsBtnPressed), for:.touchUpInside)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
No matter what I set the width or height as the button size does not change. The VC is in a navigation controller. Does anyone have any insight or next steps I can take? Any help would be appreciated
Click on your ViewController in StoryBoard. Go to "Editor" -> "Embed In" -> Click on "Navigation Controller".After that paste the code in your ViewDidLoad method where you want to see the BarButton.
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 22, height: 22))
button.setBackgroundImage(UIImage(named: "tune"), for: .normal)
button.addTarget(self, action:#selector(ViewController.settingsBtnPressed), for:.touchUpInside)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}
// The height and minimum value of this button will be affected by the rightBarButtonItem
Button height is 100000
Button height is 0
[ You can this ]
// Provide a vew to button
let tView = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 40));
tView.backgroundColor = UIColor.darkGray
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 20, height: 22))
//button.setBackgroundImage(UIImage(named: "tune"), for: .normal)
button.backgroundColor = UIColor.green;
button.addTarget(self, action:#selector(ViewController.settingsBtnPressed), for:.touchUpInside)
// add btton to tView
tView.addSubview(button)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: tView)
Turns out that the problem arises due to how bar buttons are handled in iOS 11. UIBarButtonItemnow uses autolayout instead of frames. As a result, the following code allows you to adjust the size of the button:
button.widthAnchor.constraint(equalToConstant: 22.0).isActive = true
button.heightAnchor.constraint(equalToConstant: 22.0).isActive = true