Swift: Radio button into StackView are not displayed properly - ios

I created a list of radio button in a stackView, but I do not understand why they are displayed wrong, they are not properly aligned
I want all my buttons to be correctly aligned on the left as I can solve this problem thank you!
Here is a part of the code:
var buttons = [UIButton]()
var titles = ["Lasy", "What I've been told", "I'm do into it", "Close the best i can", "Hard core"]
func setupUI() {
for title in titles {
// create button
let button = UIButton(type: .custom)
button.setTitleColor(.black, for: .normal)
button.setTitle(title, for: .normal)
button.setImage(UIImage(named: "uncheck.png")!, for: .normal)
// if the selected button cannot be reclick again, you can use .Disabled state
button.setImage(UIImage(named: "check.png")!, for: .selected)
button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 35)
button.addTarget(self, action: #selector(radioButtonAction), for: .touchUpInside)
buttons.append(button)
}
for button in buttons {
addArrangedSubview(button)
}
setupUserChoice()
}
func setupUserChoice(){
if titles.contains(value) {
let valueIndex = titles.index(of: value)
radioButtonAction(sender: buttons[valueIndex!])
}
}
func setStackView() {
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .fill
stackView.spacing = 16.0
stackView.alignment = .leading
}

The problem is with the way you are trying to set the imageEdgeInsets. It is only adjusting the image position, not increasing the size of the button accordingly. For increasing the size of the button, you need to set contentEdgeInsets. But you also need to adjust the title position according to the change in image's position. You can use titleEdgeInsets for that.
So remove you code button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 35) and replace it with :-
let leftPadding_beforeImage: CGFloat = 35
let gapBetweenImageAndTitle: CGFloat = 8
let rightPadding_afterTitle: CGFloat = 16
button.imageEdgeInsets = UIEdgeInsetsMake(0, leftPadding_beforeImage, 0, 0)
button.titleEdgeInsets = UIEdgeInsetsMake(0, (leftPadding_beforeImage+gapBetweenImageAndTitle), 0, -(leftPadding_beforeImage+gapBetweenImageAndTitle))
button.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, (leftPadding_beforeImage+gapBetweenImageAndTitle+rightPadding_afterTitle))
I hope the variable names are self-explanatory. If you want to know more about UIButton edgeInsets, I suggest you reading this fantastic answer.

Set the frame of each button, because UIStackViews use intrinsic content size. for example :
button.frame = CGRect(x: 0, y: 0, width: 100, height: 20)

Related

add bottom line to UIButton - Swift

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)

Trying to make a UIButton a circle

Im currently trying to make a button into a circle shape and here is my code:
var raffleButton:UIButton = {
var button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont(name: "AvenirNext-Bold", size: 19)
button.setTitle("Tap To Enter Raffle!", for: .normal)
button.setTitleColor(UIColor.red, for: .normal)
button.backgroundColor = .white
button.layer.masksToBounds = true
button.frame = CGRect(x: 1600, y: 160, width: 160, height: 160)
button.layer.cornerRadius = button.frame.width/2
return button
}()
However when I run the code the button is disfigured and looks like the following... round and football like.
Is there any reason why the button looks like it does instead of being a circle?
You have some confusion as to whether you are using autolayout or not.
You have set translatesAutoresizingMaskIntoConstraints to false, but then you are trying to manipulate the frame.
If you add constraints to set the width & height, you will get a result closer to what you are after, but you will still need to adjust your label or font to get it to fit:
var raffleButton:UIButton = {
var button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont(name: "AvenirNext-Bold", size: 19)
button.setTitle("Tap To Enter Raffle!!", for: .normal)
button.setTitleColor(UIColor.red, for: .normal)
button.backgroundColor = .white
button.layer.masksToBounds = true
button.heightAnchor.constraint(equalToConstant: 160).isActive = true
button.widthAnchor.constraint(equalToConstant: 160).isActive = true
button.layer.cornerRadius = 80
return button
}()
Since you set button.translatesAutoresizingMaskIntoConstraints = false, this code won't work button.frame = CGRect(x: 1600, y: 160, width: 160, height: 160). The button's size will be changed during the layout process(won't be (160, 160) anymore). Therefore, it's not a circle.
you can either change button.translatesAutoresizingMaskIntoConstraints = false or try setting button's cornerRadius in viewDidLayoutSubviews method.
your button Height same as button width and then set this code..
anyButton.backgroundColor = .clear
anyButton.layer.cornerRadius = anyButton.frame.height / 2
anyButton.layer.borderWidth = 1
anyButton.layer.borderColor = UIColor.black.cgColor
One semi-obvious thing to note, is if the button frame's height and width is not equal, it will not be a circle :).

button does not work after adding uiview in swift 4

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

UIButton titleLabel text bottom to its frame

How can i display the UIButton titleLabel text to bottom of its frame. Currently i am using the UIEdge top margin and setting the negative UIButton image width, result is not as expected. i also want to place the image center to its frame.
`
let leftButton: UIButton = {
let button = UIButton()
button.layer.borderWidth = 2
button.layer.borderColor = UIColor.ublGray1().cgColor
button.setImage(UIImage.init(named: leftButtonImage)?.withRenderingMode(.alwaysTemplate), for: .normal)
button.tintColor = UIColor.cerulean()
button.layer.masksToBounds = false
button.layer.cornerRadius = 37
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(leftButtonTitle, for: .normal)
button.titleEdgeInsets = UIEdgeInsets(top: 110, left: -26, bottom: 0, right: 0)[![enter image description here][1]][1]
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
button.setTitleColor(UIColor.charcoalGrey(), for: .normal)
button.titleLabel?.font = UIFont.aspiraMedium(size: 16)
return button
}()
`
You can try something like this.
How about setting "Title Insets" - bottom - to a negative number? It works.
But if you want it to stick to the bottom of the frame, it won't work, so... how about this:
bt.titleEdgeInsets.top = (bt.imageView?.safeAreaInsets.bottom)!
or bt.titleEdgeInsets.top = (bt.imageView?.alignmentRectInsets.bottom)!

Why is a button with an image in it making the titleLable text cut off?

I have this code below which creates a button in code and centers the button in the middle of its superview:
let cameraButton: UIButton = {
let button = UIButton()
button.setImage(UIImage(named: "cam"), for: .normal)
button.setTitle("Take Pic", for: .normal)
button.setTitleColor(UIColor.black, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
return button
}()
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
view.addSubview(cameraButton)
cameraButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
cameraButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
Everything is working fine (as in the button is being centered in the center of the view) but the titleLabel text is being cut off for some reason (shown in the picture below):
I thought buttons have an intrinsic width and height so why would the titleLabel be cut off here? Shouldn't the width just expand based on the content inside of it (the imageView as well as the label)? Can someone advise me a way to fix this?
Try with setting below attributes
cameraButton.titleLabel!.numberOfLines = 0
cameraButton.titleLabel!.adjustsFontSizeToFitWidth = true
cameraButton.titleLabel!.lineBreakMode = NSLineBreakMode.byWordWrapping

Resources