I've got a problem where I want a view (indicatorView)'s width equal to a button. I'm using Snapkit but I think this problem should be relevant with bare NSLayoutConstraint too. Here's what I'm doing to make indicatorView's width equal to button.
indicatorView.width.equalTo(button.snp.width)
However, this makes the button's width equal to the indicatorView's width, instead of making the indicatorView's width equal to buttons' width.
How can I specify the direction of the relation? Is that possible?
indicatorView.translatesAutoresizingMaskIntoConstraints = false
indicatorView.widthAnchor.constraint(equalToConstant: button.widthAnchor).isActive = true
let f = indicatorView.frame
indicatorView.frame = CGRect(x: f.origin.x, y: f.origin.y: width: button.snp.width, height: f.height)
Are you wrapping this in the correct closure? so it should look something like:
indicatorView.snp.makeConstraints { (make) in
make.width.equalTo(button)
}
Related
I created a block to add UISlider programmatically to have total control of the design. How ever it displays on the thumb image without showing the tract. I will appreciate if anyone could help me resolve the problem.
thank you.
let ageSlider: UISlider = {
let ageS = UISlider(frame:CGRect(x: 10, y: 100, width: 300, height: 20))
ageS.minimumValue = 0
ageS.maximumValue = 60
ageS.value = 24
ageS.tintColor = .green
ageS.isContinuous = true
print("creating age slider")
//ageS.maximumTrackTintColor = UIColor.trackStrokeColor
//ageS.minimumTrackTintColor = UIColor.pulsatingFillColor
ageS.translatesAutoresizingMaskIntoConstraints = false
return ageS
}()
You need to add a width constraint to your slider object:
// add age slider constraints to age view. ageView is the container of the ageSlider
// center ageSlider both horizontally and vertically
ageSlider.centerXAnchor.constraint(equalTo: ageView.centerXAnchor).isActive = true
ageSlider.centerYAnchor.constraint(equalTo: ageView.centerYAnchor).isActive = true
// constrain ageSlider width to 90% of ageView width
ageSlider.widthAnchor.constraint(equalTo: ageView.widthAnchor, multiplier: 0.9).isActive = true
Don't set translatesAutoresizingMaskIntoConstraints to false if you want to manually set the frame of the UI component.
Either set it to true:
ageS.translatesAutoresizingMaskIntoConstraints = true
or just comment that line.
If you want the size to not be static, and change when the phone orientation changes, or when the frame of the superview changes, ..., then use constraints. In your case, you are missing the width constraint.
I am using AVMakeRect to get the image coordinates this is my code for that .
let x: CGRect = AVMakeRect(aspectRatio: image.size, insideRect: pointsView.imageView.frame)
This is output:
(50.9430284857571, 40.0, 272.113943028486, 484.0)
This is my constraints set up:
This is the image I used to get the output :
You can see there is no space on top of the image view but it is sending me the y value as 40 and x value as 50 .
What was wrong with my constraints and code ?
If you uses auto layout you need to change the constraints in viewDidLayoutSubviews based on our requirements.
Add top constraint outlet.
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
topConstraint.constant = 50
}
Here is my app with the profile on the left (ProfileViewController) and a containerView on the right (ContainerViewController). What I am trying to achieve is once the containerViewController has done its job, it will update the height of the UIView.
// ContainerViewController.swift
let heightConstraint = self.view.constraints.filter { $0.identifier == "Height" }.first
heightConstraint?.constant = height
When browsing the list of constraints, they're all emtpy, and I did set up some constraints in the storyboard. So Why ? Is there any way to access the UIView within the ContainerViewController ?
Ps:
DispatchQueue.main.async {
self.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
}
Sounds to work, but I think that modify constraint is proper ? Nope ?
What I would do, is to set IBOutlet for the constraint, and store it inside ContainerView.
This way, you don't depend on order number or anything else, to get this constraint, even if code (or storyboard) will changed in the future.
And Yes, the right way is to set the constraint constant, and not changing frame.
But be aware, that even constraint constant change need to be put on the main (UI) thread - (by the look of your code, I assume, you are dealing with the threads).
The best way to describe my situations is with images. What I have is a view which contains several UILabels and UIImage. The red box is a UILabel and if the content is too big it should go to the second line.
From the storyboard I have a working case when the content fits but the problem is that I am not sure how to handle the case when the last (red box) should go to the second line. I am using autolayout and cartography.
If someone can point me to the right direction I will be very grateful.
First calcululate width of text as per your current label's position.
If text width is more than current label's width then see my answer from below link:
Auto Layout how to move the view2 from right to the bottom?
Calculate width:
func widthForView1(_ text:String, font:UIFont, height:CGFloat) -> CGFloat
{
let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: your_label_width, height: your_lable_height))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.text = text
label.font = font
label.sizeToFit()
return label.frame.width
}
You cannot do that with constraints only. To change the entire position of the element on the screen, you need to do it programmatically.
Use of tag View can solve this issue. TagListView is an external library.
When u add a view as subclass of taglistView, its height automatically increases accordingly.
ADD this to pod file : pod 'TagListView'
func addTags() {
let str1 = "Hi"
tagListView.addTag(str1)
let str2 = "Helloo"
tagListView.addTag(str2)
let str3 = "How Are u ? "
tagListView.addTag(str2)
tagListView.isUserInteractionEnabled = false
}
I have been trying to make the UIButton in the cells a perfect circle. Unfortunately the circle has been formed based on the background image rather than the UIButton frame.
The code I have for creating a circle:
cell.StoryViewButton.setImage(image, forState: .Normal)
cell.StoryViewButton.frame = CGRectMake(50, 8, 100, 100)
cell.StoryViewButton.layer.masksToBounds = false
cell.StoryViewButton.layer.cornerRadius = cell.StoryViewButton.frame.width/2
cell.StoryViewButton.clipsToBounds = true
The output looks like this:
What can I do to get the perfect circle button frames that I want?
Try something like this
cell.StoryViewButton.layer.masksToBounds = true
cell.StoryViewButton.layer.cornerRadius = cell.StoryViewButton.frame.width/2
If you need to create a circle of view you have to set masksToBounds to true, do not set clipsToBounds
Hope this will help you.
Swift 4
You could apply the following function to any view, including buttons.
func makeViewCircular(view: UIView) {
view.layer.cornerRadius = view.bounds.size.width / 2.0
view.clipsToBounds = true
}
Great.
That didn't work for me at first as I applied it in the viewDidLoad, though. At this point, constraints are still playing with the size of your buttons and the corner radius is applied to a button it thinks is twice the size, resulting in the odd shapes you have. To apply the right values to the right measurements, place the code in override func viewDidLayoutSubviews().
I know this may be a more specific case within my personal process, yet I'm sure it'll help somebody.
There is the working code.I test it. Hope it helps.
I am not sure why but I check that by changing height and width of the frame in here "CGRectMake(50, 8, 120, 120)" that the height and width of the frame and height and width of a button should be same to get the perfect circle.
cell.StoryViewButton.setImage(image, forState: .Normal)
cell.StoryViewButton.frame = CGRectMake(50, 8, 120, 120)
cell.StoryViewButton.layer.cornerRadius = self.btn.frame.width/2;
cell.StoryViewButton.layer.masksToBounds = true
Hope it helps.