How do I change UIView Size? - uiview

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

Related

How can we achieve dynamic items with dynamic content in custom table cell?

How can I achieve the dynamic no of items with dynamic content size one after other and in next line if the content gets more than superview in a custom table view cell?
Please refer image for question clarification.
The question you posted is a bit long and actually requests for multiple things since you didn't post what you have tried and what part you are having trouble with. There are many ways of doing this so let's start with normal label:
An UILabel can have attributed string under attributedText which can be used to achieve the visual design you are showing in your image. To lay them out horizontally we could use sizeToFit to get their width. Assume something like:
func layoutLabels(_ labels: [UILabel], inView view: UIView, horizontalSeparator: CGFloat = 4.0) {
var x: CGFloat = 0.0
labels.forEach { label in
label.sizeToFit() // Will make it's size just right
label.frame = CGRect(x: x, y: 0.0, width: label.frame.width, height: label.frame.height)
x = label.frame.maxX + horizontalSeparator
view.addSubview(label)
}
}
Now to add vertical part we simply need to add maximum width and also add y component:
func layoutLabels(_ labels: [UILabel], inView view: UIView, maximumWidth: CGFloat, lineHeight: CGFloat, horizontalSeparator: CGFloat = 4.0, verticalSeparator: CGFloat = 2.0) {
var x: CGFloat = 0.0
var y: CGFloat = 0.0
labels.forEach { label in
label.sizeToFit() // Will make it's size just right
var newX = x + label.frame.width
if newX > maximumWidth {
if x == 0.0 {
// We are at the beginning of the line and a single label is simply too large. We will need to reduce it's width
label.frame = CGRect(x: x, y: y, width: maximumWidth, height: label.frame.height)
} else {
// We should go into new line
x = 0.0
y += lineHeight
label.frame = CGRect(x: x, y: y, width: min(label.frame.width, maximumWidth), height: label.frame.height)
newX = x + label.frame.width
}
} else {
label.frame = CGRect(x: x, y: y, width: min(label.frame.width, maximumWidth), height: label.frame.height)
}
x = newX + horizontalSeparator
view.addSubview(label)
}
}
This should now let you fill labels the way as on your image. We are also checking for line breaks and labels that can not fit overall width of your view. So now we need to define what is the actual size of your view. y should return that but we need to be able to use it in a table view cell. So we can simply return it:
func layoutLabels(_ labels: [UILabel], inView view: UIView, maximumWidth: CGFloat, lineHeight: CGFloat, horizontalSeparator: CGFloat = 4.0, verticalSeparator: CGFloat = 2.0) -> CGFloat {
...
return labels.count > 0 ? y + lineHeight : 0.0
}
Now in your table view cell it might be best to use some constraint outlet:
protocol Tag {
func createLabel() -> UILabel
}
class Cell: UITableViewCell {
#IBOutlet private var tagsPanel: UIView!
#IBOutlet private var tagsPanelHeightConstraint: NSLayoutConstraint?
var tags: [Tag]!
func refresh() {
tagsPanel.subviews.forEach { $0.removeFromSuperview() } // Ugly, needs improvement
let height = layoutLabels(tags.map { $0.createLabel() }, inView: tagsPanel, maximumWidth: tagsPanel.frame.width, lineHeight: 40.0)
tagsPanelHeightConstraint?.constant = height
}
}
Now the problem is that your table view needs to refresh because your table view cell might have resized. You will need to have a reference to your table view and simple call begin/end updates on it.
var tags: [Tag]!
weak var tableView: UITableView? // Assigned in cellForRowAtIndexPath
func refresh() {
tagsPanel.subviews.forEach { $0.removeFromSuperview() } // Ugly, needs improvement
let height = layoutLabels(tags.map { $0.createLabel() }, inView: tagsPanel, maximumWidth: tagsPanel.frame.width, lineHeight: 40.0)
if let tagsPanelHeightConstraint = tagsPanelHeightConstraint, tagsPanelHeightConstraint.constant != height {
tagsPanelHeightConstraint.constant = height
tableView?.beginUpdates()
tableView?.endUpdates()
}
}
Good luck.

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.

Change the height of UISegmented Control using IB?

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

How to center UIButton in Swift?

I have this code for my UIButton. What should I change in my CGRectMake to set my UIButton in the center of the screen for all screen sizes?
let loginBtn = UIButton(frame: CGRectMake(60, 360, 240, 40))
loginBtn.layer.borderColor = UIColor.whiteColor().CGColor
loginBtn.layer.borderWidth = 2
loginBtn.titleLabel!.font = UIFont.systemFontOfSize(24)
loginBtn.tintColor = UIColor.whiteColor()
loginBtn.setTitle("Login", forState: UIControlState.Normal)
self.view.addSubview(loginBtn)
For your place uibutton center of your view , update your cgrectmake as bleow..
CGRectMake((self.view.frame.size.width - 240) / 2, (self.view.frame.size.height - 40) / 2,240,40)
or
You can add one line after your code
loginBtn.center = self.view.center
For SignUp Button :
 
signup.frame = loginBtn.bounds
signup.center = CGPointMake(loginBtn.center.x, loginBtn.center.y + loginBtn.frame.size.height + 10)
Set your UIButton's center to the center of the view it is in.
loginBtn.center = view.center
You need add the following line prior to self.view.addSubview(loginBtn).
loginBtn.center = self.view.center
This will center the button across the whole screen, not just the view it's in:
let verticalCenter: CGFloat = UIScreen.mainScreen().bounds.size.height / 2.0
let horizontalCenter: CGFloat = UIScreen.mainScreen().bounds.size.width / 2.0
loginBtn.center = CGPoint(x: horizontalCenter, y: verticalCenter)
Edit:
As #LeoDabus pointed out, this can be compacted by using the midX and midY properties on CGRect:
let verticalCenter: CGFloat = UIScreen.mainScreen().bounds.midY
let horizontalCenter: CGFloat = UIScreen.mainScreen().bounds.midX
For Swift 4
#IBOutlet weak var btStart: UIButton!
on the middle of any screen (any device)
btStart.center = self.view.center
OR
btStart.center.x = self.view.center.x
btStart.center.y = self.view.center.y
on the center by x and 25 percent from top
btStart.center.x = self.view.center.x
btStart.center.y = self.view.center.y / 2
I found this to be the best solution for me..
Swift 4
myButton.center.x = self.view.frame.midX
myButton.center.y = self.view.frame.midY
I found if I need to center things quite often, I usually use a generic solution.
extension UIViewController {
func centerComponent(_ component: AnyObject) {
let customView = component as! UIView
customView.center.x = self.view.frame.midX
customView.center.y = self.view.frame.midY
}
}
then you can call it from any UIViewcontroller inside a function like so:
centerComponent(myButton)

ios: Center view in its superview

I'm trying to center my subview with a button in itssuperview. So I want the center of the subview be the center of the superview. I'm trying that with following code:
override func viewDidLoad() {
self.view.backgroundColor = UIColor.redColor()
var menuView = UIView()
var newPlayButton = UIButton()
//var newPlayImage = UIImage(named: "new_game_button_5cs")
var newPlayImageView = UIImageView(image: UIImage(named: "new_game_button_5cs"))
newPlayButton.frame = CGRectMake(0, 0, newPlayImageView.frame.width, newPlayImageView.frame.height)
newPlayButton.setImage(newPlayImage, forState: .Normal)
newPlayButton.backgroundColor = UIColor.whiteColor()
menuView.center = self.view.center
menuView.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2)
menuView.backgroundColor = UIColor.whiteColor()*/
menuView.addSubview(newPlayButton)
}
Unfortunately it doesent seem to work as this is the result:
UIView *subview = your View To Be Centered In Its SuperView;
UIView *superView = subview.superview;
subview.center = [superView convertPoint:superView.center
fromView:superView.superview];
If view is nil(on fromView:), this method instead converts from window base coordinates. Otherwise, both view and the receiver must belong to the same UIWindow object.
NOTE: If you use the auto layout stuff, then you have to change the constraints . not the frame or center.
Good Luck :)
Try removing your view width from your superview width, e.g.:
var width: CGFloat = (self.view.bounds.size.width / 2)
// (here goes your view width that you want centralize)
menuView.center = CGPointMake(width, self.view.bounds.size.height / 2)
My working code
vRate = superview
rcRating = view ( that I want to centralize in vRate )
self.rcRating = AMRatingControl(location: CGPoint(x: 0, y: 0), andMaxRating: 5)
self.vRate.addSubview(self.rcRating)
var width: CGFloat = (self.vRate.bounds.size.width / 2) - self.rcRating.bounds.size.width
self.rcRating.center = CGPointMake(width, self.vRate.bounds.size.height / 2)

Resources