Change the height of UISegmented Control using IB? - ios

How can i change the height of UISegmented control. I'm using Swift 3.0 with xcode 8. Height property is disabled by default.

I found this:
https://stackoverflow.com/a/41889155/7652057
#IBDesignable class MySegmentedControl: UISegmentedControl {
#IBInspectable var height: CGFloat = 29 {
didSet {
let centerSave = center
frame = CGRect(x: frame.minX, y: frame.minY, width: frame.width, height: height)
center = centerSave
}
}
}
https://stackoverflow.com/a/37716960/7652057
One of three options from the link,
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let rect = CGRect(origin: segment.frame.origin, size: CGSize(width: segment.frame.size.width, height: 100))
segment.frame = rect
}

Ok, I was trying to do it for a long while and here is the solution.
Firstly, It is possible within IB but for that we need to have a good bunch of autolayout constraints.
I've placed that Segmented control in a UIVIew with all the edges pinned inside it.
Then I gave the desired height to that view and it worked.
Also.. thanks to all of your answer

It's very easy. You can access it programmaticly by using frame's height:
yourSegmentedControllOutlet.frame.size.height = yourHeight

Related

How to align text in UIButton below UIImage because it is not showing up correctly

I have a problem in my navigation where my buttons are not displayed correctly. I want 2 rows of 3 buttons each. Each button has an image and a label. The label should be centered and below the image. But that's the tricky thing i can't seem to get working correctly because every time I start the emulator the first button looks okay and all the others are displayed correctly in therms of the image but not the label. I tried to mess with the size of the buttons but noting seems to be working.
I also tried to use the code from that question on stackoverflow but i didn't work out correctly. because the image wasn't displayed at all but the sizing was correct. Furthermore the label was only shown on the first button.
I'm using a IBDesignable to extend the UIButton class which I'm assigning to the Buttons
import UIKit
#IBDesignable
class VerticalButton: UIButton {
#IBInspectable public var padding: CGFloat = 20.0 {
didSet {
setNeedsLayout()
}
}
override var intrinsicContentSize: CGSize {
let maxSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
if let titleSize = titleLabel?.sizeThatFits(maxSize), let imageSize = imageView?.sizeThatFits(maxSize) {
let width = ceil(max(imageSize.width, titleSize.width))
let height = ceil(imageSize.height + titleSize.height + padding)
return CGSize(width: width, height: height)
}
return super.intrinsicContentSize
}
override func layoutSubviews() {
if let image = imageView?.image, let title = titleLabel?.attributedText {
let imageSize = image.size
let titleSize = title.size()
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + padding), right: 0.0)
imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + padding), left: 0.0, bottom: 0.0, right: -titleSize.width)
}
super.layoutSubviews()
}
}
I'm guessing I made an error while calculating in the intrinsicContentSizeof the button.
I also double checked if the class was assigned to all the relevant button and that each button had a label. Beside that I also checked that there were no insets set via the interface builder.
So far I had no luck in finding a solution hence my question. I appreciate your help. If you need more information please don't hesitate to reach out. I will be happy to provide it.
Thanks
Thanks to #DonMag help I've found out that the issue was not with the code instead with the size of the images.

how to make designable textfield code class in swift

I am a beginner in programming and in iOS development. I want to make a swift file that contains a code to make Designable textfield, so I will not edit the UI element display by coding, all the UI that will be edited, I will edit it in Interface builder.
I need to input an image in UITextfield, and I follow along a tutorial in here https://www.youtube.com/watch?v=PjXOUd4hI6U&t=932s to put an image in the left side of the UITextField, like the lock image in the picture above. here is the the to do this
import UIKit
#IBDesignable
class DesignableTextField: UITextField {
#IBInspectable var leftImage : UIImage? {
didSet {
updateView()
}
}
#IBInspectable var leftPadding : CGFloat = 0 {
didSet {
updateView()
}
}
#IBInspectable var cornerRadiusOfField : CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadiusOfField
}
}
func updateView() {
if let image = leftImage {
leftViewMode = .always
// assigning image
let imageView = UIImageView(frame: CGRect(x: leftPadding, y: 0, width: 20, height: 20))
imageView.image = image
var width = leftPadding + 20
if borderStyle == UITextBorderStyle.none || borderStyle == UITextBorderStyle.line {
width += 5
}
let view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: 20)) // has 5 point higher in width in imageView
view.addSubview(imageView)
leftView = view
} else {
// image is nill
leftViewMode = .never
}
}
}
but now I need add another image on the right side only and both of them (i.e on the the right side AND left side). how do I edit those code? I have tried but it doesn't appear and to be honest I little bit confused to adjust the x and y coordinate of the view. I need your help :)
There are two solutions for this
The First solution is the easiest one. You can have a view and insert inside the view a UIImageView, UITextField, UIImageView. Add constraints to set the desired sizes. You can make the text field transparent. With this method, you can customize it how you want.
The Second solution is how you are doing it.
The first thing you need to do is add the properties to the right image and right padding. Under the left padding property add the following code:
#IBInspectable var rightImage : UIImage? {
didSet {
updateRightView()
}
}
#IBInspectable var rightPadding : CGFloat = 0 {
didSet {
updateRightView()
}
}
With this new properties, you can choose the image and edit the x location.
After the update function create a new function called updateRigthView
Like this:
func updateRightView() {
if let image = rightImage {
rightViewMode = .always
// assigning image
let imageView = UIImageView(frame: CGRect(x: rightPadding, y: 0, width: 20, height: 20))
imageView.image = image
var width = rightPadding - 20
if borderStyle == UITextBorderStyle.none || borderStyle == UITextBorderStyle.line {
width -= 5
}
let view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: 20)) // has 5 point higher in width in imageView
view.addSubview(imageView)
rightView = view
} else {
// image is nill
rightViewMode = .never
}
}
You had to edit the right properties.Now head to storyboard and try it out. To move the image to the left decrease the right padding 0,-1,-2,-3, etc. To move the image to the right increase the right padding 0,1,2,3.

UIButton subview is offset in subclass

I have a UIButton subclass intended to show a selected state of a button. The selected state simply places a thick black line at the bottom of the button view and when unselected it hides the black line. However, when using this in a UIButton subclass, the black line view is offset. I have tried playing around with insets, but I don't think that is the problem. Here is my subclass:
class TabButton: UIButton {
private var height:CGFloat = 5
private var selectedIndicator:UIView?
override var isSelected: Bool {
didSet {
selectedIndicator?.isHidden = !isSelected
}
}
fileprivate func initializeSelector(_ frame: CGRect) {
selectedIndicator = UIView(frame: CGRect(x: 0, y: frame.size.height - height, width: frame.size.width, height: height))
selectedIndicator?.backgroundColor = UIColor.black
self.addSubview(selectedIndicator!)
}
override func awakeFromNib() {
super.awakeFromNib()
initializeSelector(self.frame)
}
}
The desired button should look like this:
But instead it looks like this:
Can anyone help me understand what is happening here and how to fix it? Thanks!
Try this, in layoutSubviews you get the final frame:
override layoutSubviews() {
super.layoutSubviews()
selectedIndicator.frame = CGRect(x: 0, y: frame.size.height - height, width: frame.size.width, height: height)
}
The frame of the selectedIndicator is set only once when initializeSelector is called. When the button changes its frame, it does not change the frame of subviews, you need to manually update the frame of selectedIndicator.
To do so, you need to override layoutSubviews() method of UIView.
override layoutSubviews() {
super.layoutSubviews()
selectedIndicator?.frame = CGRect(x: 0, y: frame.size.height - height, width: frame.size.width, height: height)
}
See this answer to know when layoutSubviews() is called.

getting highly confused by odd behaviour of viewController Method

I have overrided a method as
override func viewDidLayoutSubviews() {
// creating bottom line for textField
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor.whiteColor().CGColor
border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - width, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height)
border.borderWidth = width
emailTextField.layer.addSublayer(border)
emailTextField.layer.masksToBounds = true
}
Now whats happening is that when I run my app on Iphone 6, 6+ every thing works fine. But when I run the same code on iphone5 (Simulator + real Device ) viewDidLayoutSubViews is getting called infinite times and my app becoms unresponsive. I solved the problem by using a bool variable. But I do not understand why is this happening. So can someone please explain this to me.
Thanks :-)
As docs says that viewDidLayoutSubviews method need for change layout
Called to notify the view controller that its view has just laid out
its subviews. When the bounds change for a view controller's view,
the view adjusts the positions of its subviews and then the system
calls this method. However, this method being called does not indicate
that the individual layouts of the view's subviews have been
adjusted. Each subview is responsible for adjusting its own layout.
Move your code to viewDidLoad method or to loadView if you are not using xibs or Storyboards
override func viewDidLoad() {
// creating bottom line for textField
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor.whiteColor().CGColor
border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - width, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height)
border.borderWidth = width
emailTextField.layer.addSublayer(border)
emailTextField.layer.masksToBounds = true
}
If you would like to change border.frame you can set it to class variable and change it in viewDidLayoutSubviews method
override func viewDidLayoutSubviews() {
self.border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - width, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height)
self.border.borderWidth = width
}
Just replace
emailTextField.layer.addSublayer(border)
with this:
emailTextField.addSublayer(border)
-> you want to add sublayer to a view - as you want to apply masksToBounds property to it either.
Move your implementation inside viewDidLayoutSubviews. I got the same issue. Hope it will work.
override func viewDidLayoutSubviews()
{
//Your CODE
}

How do I change UIView Size?

I have trouble with modifying my UIView height at launch.
I have to UIView and I want one to be screen size * 70 and the other to fill the gap.
here is what I have
#IBOutlet weak var questionFrame: UIView!
#IBOutlet weak var answerFrame: UIView!
let screenSize:CGRect = UIScreen.mainScreen().bounds
and
questionFrame.frame.size.height = screenSize.height * 0.70
answerFrame.frame.size.height = screenSize.height * 0.30
It has no effect on the app during run time.
I use autolayout but I only have margins constraints...
Am I doing it all wrong?
This can be achieved in various methods in Swift 3.0 Worked on Latest version MAY- 2019
Directly assign the Height & Width values for a view:
userView.frame.size.height = 0
userView.frame.size.width = 10
Assign the CGRect for the Frame
userView.frame = CGRect(x:0, y: 0, width:0, height:0)
Method Details:
CGRect(x: point of X, y: point of Y, width: Width of View, height:
Height of View)
Using an Extension method for CGRECT
Add following extension code in any swift file,
extension CGRect {
init(_ x:CGFloat, _ y:CGFloat, _ w:CGFloat, _ h:CGFloat) {
self.init(x:x, y:y, width:w, height:h)
}
}
Use the following code anywhere in your application for the view to set the size parameters
userView.frame = CGRect(1, 1, 20, 45)
Here you go. this should work.
questionFrame.frame = CGRectMake(0 , 0, self.view.frame.width, self.view.frame.height * 0.7)
answerFrame.frame = CGRectMake(0 , self.view.frame.height * 0.7, self.view.frame.width, self.view.frame.height * 0.3)
Swift 3 and Swift 4:
myView.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
Hi create this extends if you want. Update 2021 Swift 5
Create File Extends.Swift and add this code (add import foundation where you want change height)
extension UIView {
var x: CGFloat {
get {
self.frame.origin.x
}
set {
self.frame.origin.x = newValue
}
}
var y: CGFloat {
get {
self.frame.origin.y
}
set {
self.frame.origin.y = newValue
}
}
var height: CGFloat {
get {
self.frame.size.height
}
set {
self.frame.size.height = newValue
}
}
var width: CGFloat {
get {
self.frame.size.width
}
set {
self.frame.size.width = newValue
}
}
}
For Use (inherits Of UIView)
inheritsOfUIView.height = 100
button.height = 100
print(view.height)
For a progress bar kind of thing, in Swift 4
I follow these steps:
I create a UIView outlet : #IBOutlet var progressBar: UIView!
Then a property to increase its width value after a user action var progressBarWidth: Int = your value
Then for the increase/decrease of the progress progressBar.frame.size.width = CGFloat(progressBarWidth)
And finally in the IBACtion method I add progressBarWidth += your value for auto increase the width every time user touches a button.
You can do this in Interface Builder:
1) Control-drag from a frame view (e.g. questionFrame) to main View, in the pop-up select "Equal heights".
2)Then go to size inspector of the frame, click edit "Equal height to Superview" constraint, set the multiplier to 0.7 and hit return.
You'll see that constraint has changed from "Equal height to..." to "Proportional height to...".
Assigning questionFrame.frame.size.height= screenSize.height * 0.30 will not reflect anything in the view. because it is a get-only property. If you want to change the frame of questionFrame you can use the below code.
questionFrame.frame = CGRect(x: 0, y: 0, width: 0, height: screenSize.height * 0.70)
I know that there is already a solution to this question, but I found an alternative to this issue and maybe it could help someone.
I was having trouble with setting the frame of my sub view because certain values were referring to its position within the main view. So if you don't want to update your frame by changing the whole frame via CGRect, you can simply change a value of the frame and then update it.
// keep reference to you frames
var questionView = questionFrame.frame
var answerView = answerFrame.frame
// update the values of the copy
questionView.size.height = CGFloat(screenSize.height * 0.70)
answerView.size.height = CGFloat(screenSize.height * 0.30)
// set the frames to the new frames
questionFrame.frame = questionView
answerFrame.frame = answerView

Resources