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.
Related
I have a vertical normal looking bar chart created with iOS Charts. My issue is that for some reason whenever I run the program, the chart does not fill up the view it is in from top to bottom. I am specifically trying to fix the fact that there is a small space between the bottom of a bar and the bottom of the UIView. How can I remove this space so the bottom of the bar aligns perfectly with the bottom of the UIView? (Need No gap)
Here is my code:
barChartView.xAxis.labelPosition = .top
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.xAxis.drawAxisLineEnabled = false
barChartView.leftAxis.drawGridLinesEnabled = false
barChartView.leftAxis.drawAxisLineEnabled = false
barChartView.rightAxis.drawAxisLineEnabled = false
barChartView.rightAxis.drawGridLinesEnabled = false
barChartView.rightAxis.enabled = false
barChartView.leftAxis.enabled = false
barChartView.xAxis.labelTextColor = UIColor.white
barChartView.data?.setDrawValues(false)
barChartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Bold", size: 12.0)!
barChartView.legend.enabled = false
barChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values:xValues)
barChartView.xAxis.granularity = 1
barChartView.animate(xAxisDuration: 1.0, yAxisDuration: 1.0, easingOption: .easeInQuint)
barChartView.isUserInteractionEnabled = false
barChartView.barData?.barWidth = 0.65
Here is a pic of the issue...I need to get rid of that gap between the bottom of the bar and the red space. The UIView that the graph is in (Not the same as the red view) reaches down to the border of the red view.
Try this:
barChartView.minOffset = 0.0
If this is not worked, add this too.
barChartView.extraBottomOffset = -10
I can't discover special options in BarChartView to resolve your problem. But I can suggest another way. You can embed your barChartView into another view and set a vertical space constraint from between bottom of your barChartView to bottom a superview with a negative value, also set clipToBounds = true for the superview. So the bottom of barChartView will be below the bottom of superview and will be cut.
View after embedding (yellow background - superview, white - barChartView).
View after bottom constraint was set to -14.
Was able to solve my problem by adjusting the bottom constraint programmatically based on the size of the phone's display.
I added this code into viewWillAppear and I will continue to do this for the rest of the iPhone sizes and not just the Xs:
if UIScreen.main.bounds.height == 896{
print("Xs Max")
bottomConstraintGraph.constant = -31.5 // bottomConstraintGraph is the constraint connected from the bottom of the graph's view to the superview and changed here through an outlet connection.
}
I add UIViews dynamically in code. There are a lot of views I want to add. Here is one for example:
let typeImage = UIImageView()
typeImage.translatesAutoresizingMaskIntoConstraints = false
rootView.addSubview(typeImage)
typeImage.widthAnchor.constraint(equalToConstant: 28).isActive = true
typeImage.heightAnchor.constraint(equalToConstant: 28).isActive = true
typeImage.leftAnchor.constraint(equalTo: rootView.leftAnchor, constant: 4).isActive = true
typeImage.topAnchor.constraint(equalTo: rootView.topAnchor, constant: 4).isActive = true
typeImage.backgroundColor = gh.myRed
typeImage.image = UIImage(named: "ic_question_bej")
I want to count sum of all elements that I add and finally set this counted value to my root view height. The problem is that
typeImage.frame.size.height
typeImage.bounds.size.height
always return 0.0
So how can I get height in CGFloat of newly added UIView via code?
Maybe I should set height of rootview to wrap all my subview in another way?
Edit
Xcode loads view with some delay and if you will try to get view size immediately after adding it to parent you will get 0.0 sizes.
You have to call yourCustomView.layoutIfNeeded() before cheking sizes.
Thanks Chenjtc for right Answer.
you can add the code like this:
typeImage.layoutIfNeeded()
before the code :
typeImage.frame.size.height
typeImage.bounds.size.height
constraint will not layout immediately, you should use layoutIfNeeded to layout the view, then you can get th frame
If you want the sum of multiple views height in CGFloat you can do it like this :
let viewHeight = self.view.frame.height //this in CGFloat
let sumHeight = viewHeight + ... other UIViews
print(sumHeight) // 568.0 for iPhone SE
or if you want to set your new UIView height you can do it by changing :
typeImage.heightAnchor.constraint(equalToConstant: 28).isActive = true
//
To :
typeImage.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 1).isActive = true
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)
}
I have a UIView in my swift code
let profile_inf_wrapper: UIView = {
let v = UIView()
v.backgroundColor = .red
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
profile_inf_wrapper.topAnchor.constraint(equalTo: view.topAnchor, constant:64).isActive = true
profile_inf_wrapper.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
profile_inf_wrapper.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
profile_inf_wrapper.heightAnchor.constraint(equalToConstant: view.frame.height/4).isActive = true
backgroundImageView.topAnchor.constraint(equalTo: profile_inf_wrapper.topAnchor).isActive = true
backgroundImageView.leftAnchor.constraint(equalTo: profile_inf_wrapper.leftAnchor).isActive = true
backgroundImageView.rightAnchor.constraint(equalTo: profile_inf_wrapper.rightAnchor).isActive = true
backgroundImageView.bottomAnchor.constraint(equalTo: profile_inf_wrapper.bottomAnchor).isActive = true
profileImage.centerYAnchor.constraint(equalTo: profile_inf_wrapper.centerYAnchor).isActive = true
profileImage.leftAnchor.constraint(equalTo: view.leftAnchor, constant:25).isActive = true
profileImage.widthAnchor.constraint(equalToConstant: 110).isActive = true
profileImage.heightAnchor.constraint(equalToConstant: 110).isActive = true
usernameLabel.topAnchor.constraint(equalTo: profile_inf_wrapper.topAnchor, constant:40).isActive = true
usernameLabel.leftAnchor.constraint(equalTo: profileImage.rightAnchor, constant:20).isActive = true
countryIcon.topAnchor.constraint(equalTo: usernameLabel.bottomAnchor, constant:10).isActive = true
countryIcon.leftAnchor.constraint(equalTo: profileImage.rightAnchor, constant:20).isActive = true
countryIcon.widthAnchor.constraint(equalToConstant: 25).isActive = true
countryIcon.heightAnchor.constraint(equalToConstant: 25 ).isActive = true
countryName.topAnchor.constraint(equalTo: usernameLabel.bottomAnchor, constant:5).isActive = true
countryName.leftAnchor.constraint(equalTo: countryIcon.rightAnchor, constant:10).isActive = true
countryName.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
All these elements are the subviews of profile_inf_wrapper.Sometimes view.frame.height/4 is too small and i want to be able to resize the UIView based on it's content
There's a property in UIView called intrinsicContentSize. It returns the smallest size that the view would need show all of it's content.
While the default implementation is not very useful because a UIView doesn't have any content on it's own, all of the default subclasses implement it.
A UILabel will return a size that fits the text perfectly, and a UIButton will return a size that fits it's contents plus whatever spacing you've added. You get the gist of it.
You can take advantage of this property by only constraining either width or height of a view, not both. If you constrain the width of a UILabel and add more text, it will grow vertically.
Finally, when you add subviews to a UIView, and you add constraints to both margins of an axis (top and bottom or left and right), as long as there's a "chain" of constraints and views, and the view doesn't have any constraints on the size, it will expand to fit.
For example, if you have a view with a label and a button, vertically arranged, if the label is constrained to the top, then constrained to the button, and the button is constrained to the bottom, as long as the container view doesn't have a height constraint, it will expand to fit the two views plus the margins perfectly.
Your goal should always be to use the least amount of constraints to express your design, without removing useful constraints. Make sure you take advantage of the intrinsicContentSize.
For setting the height of uiview dynamically you have to add height/bottom constraint to the view in your problem it might be
profile_inf_wrapper.heightAnchor.constraint(equalToConstant: view.frame.height/4+countryName.frame.size.height).isActive = true
you also need the view size to fit to get actual updated size
like
countryName.sizeToFit()
And then update layout if needed to get all affect
The first thing you want to do is make a reference to the height constraint of profile_inf_wrapper.
var profile_inf_wrapper_height_constraint: NSLayoutConstraint?
I don't know the details of your content, but when the view needs resized, you can check that with a conditional in your viewController,
if contentRequiresResizing {
profile_inf_wrapper_height_constraint.constant = view.frame.width/3
else {
profile_inf_wrapper_height_constraint.constant = view.frame.width/4
}
By referencing constraints, it allows you to support dynamic UI changes easily.
As a side note, I would recommend renaming your UIView variable name so that the reference constraint isn't so long. The Swift 3 API guidelines also support lowerCamelCase, as opposed to underscore naming.
I've created a Label with the following code :
func setupValueLabel() {
valueLabel.numberOfLines = 1
valueLabel.font = UIFont(name: "Avenir-Black", size: 50)
valueLabel.adjustsFontSizeToFitWidth = true
valueLabel.clipsToBounds = true
valueLabel.backgroundColor = UIColor.greenColor()
valueLabel.textColor = valuesColor
valueLabel.textAlignment = NSTextAlignment.Center
}
I don't really understand why but the label is not vertically centered :
Do I have to do anything specific so it can be centered ?
The problem is that font size is shrunk by adjustsFontSizeToFitWidth = true, but it does not adjust the lineHeight automatically. It remains to be for original font size that is 50.
By default, the text is aligned to its baseline. you can adjust it with baselineAdjustment property.
In your case, you should set it to UIBaselineAdjustment.alignCenters.
valueLabel.baselineAdjustment = .alignCenters
Thanks to #rintaro, it works finally.
One more thing for my case, it didn't work because I was setting ByWordWrapping. I had to set lineBreakMode as ByClipping.