iOS aspect fit and center - ios

I'd like to call
[self.view setContentMode:UIViewContentModeScaleAspectFit | UIViewContentModeCenter];
where self is an instance of UIViewController. This doesn't seem to work; what are the direct alternatives, if any?

The contentMode is not a mask; you can't use | to combine values, you'll have to pick one. UIViewContentModeScaleAspectFit should center the content if it doesn't fit the view.

You will need to set contentMode once when the view loads and then center it in viewWillLayoutSubviews which is called upon device rotation.
override func viewDidLoad() {
super.viewDidLoad()
//additional code to instantiate and setup image
imageView.contentMode = .ScaleAspectFit
self.view.addSubview(profileImageView)
}
override func viewWillLayoutSubviews() {
imageView.center.x = view.center.x
//or imageView.center = view.center
//or imageView.center.y = view.center.y
}

Related

UIView - What override will allow updating a UIView frame

I have a UIView .xib, and am subclassing UIView. When I load the Nib, the frame of the view is set and awakeFromNib() is called.
I have 3 buttons. When I load the view, I pass in callbacks for each button. If one or more of the callbacks is nil, then I hide the buttons and resize the view:
let viewSize = 50
var adjustedSize = 0
if (self.option2String == nil){
self.option2View.isHidden = true
adjustedSize -= viewSize
}
if (self.option3String == nil){
self.option3View.isHidden = true
adjustedSize -= viewSize
}
let _size = self.innerView.frame.size
let size = CGSize(width: _size.width, height: _size.height + CGFloat(adjustedSize))
self.innerView.frame = CGRect(origin: self.innerView.frame.origin, size: size)
I have tried putting this code in awakeFromNib(), and didMoveToSuperview(), but the frame does not change size.
If I enclose the last line in DispatchQueue.main.async, then it works. But I'm concerned that this is just luck due to timing.
Is this best practice? Where can I resize a view from within a UIView subclass?
EDIT: Confirmed, the DispatchQueue.main.async is just luck. It only works 50% of the time.
Having the view inside a UIViewController, call a function that resizes your view inside the controller's viewDidLayoutSubviews()
override func viewDidLayoutSubviews() {
myView.resize()
}

Circular views with Autolayout (snapkit)?

I am trying to make a circular view which has an adaptive size based on auto layout, currently i set the constraints, then i attempt to round the image in the viewwilllayoutsubviews method.
This is resulting in oddly shaped views that are not circular, how can i resolve this?
init:
profilePic = UIImageView(frame: CGRect.zero)
profilePic.clipsToBounds = true
profilePic.contentMode = .scaleAspectFill
constrains:
profilePic.snp.makeConstraints { (make) -> Void in
make.centerX.equalTo(self).multipliedBy(0.80)
make.centerY.equalTo(self).multipliedBy(0.40)
make.size.equalTo(self).multipliedBy(0.22)
}
subviews:
override func viewWillLayoutSubviews() {
self.navigationMenuView.profilePic.layer.cornerRadius = self.navigationMenuView.profilePic.frame.size.width / 2.0
self.navigationMenuView.profilePic.layer.borderWidth = 2
self.navigationMenuView.profilePic.layer.borderColor = UIColor.white.cgColor
}
result:
I guess you want this (sorry for the plain autolayout, but I don't use snapkit):
profilePic.heightAnchor.constraint(equalTo: profilePic.widthAnchor).isActive = true
profilePic.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.22).isActive = true
Instead of this:
make.size.equalTo(self).multipliedBy(0.22)
I had the same problem
This is my solution:
let profilePicHeight: CGFloat = 30.0
Add this line of code to your constrains:
profilePic.snp.makeConstraints { (make) -> Void in
make.height.width.equalTo(self.profilePicHeight)
...
}
then:
override func viewWillLayoutSubviews() {
self.navigationMenuView.profilePic.layer.cornerRadius = self.profilePicHeight / 2.0
...
}
My suggestion here is don't treat it like a circular view from the outside of it. Make the view itself conform to being a circle so that you can use it anywhere.
INSIDE the view give it constraints like...
widthAnchor.constraint(equalTo: heightAnchor).isActive = true
This will make it square (with undetermined size).
Then in the function layoutSubviews...
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.size.width * 0.5
}
This will make the square into a circle.

swift: Centre alignment for the text of labels and buttons

Programmatically i have created a View and added a label and buttons to it. its fine in vertical it aligns to centre but as i rotate the screen it does not aligns to centre rather it seems as left aligned.
This is my code:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 150))
headerView.layer.borderWidth = 1
headerView.layer.borderColor = UIColor.whiteColor().CGColor
headerView.backgroundColor = ClientConfiguration.primaryUIColor()
let myLabel = UILabel()
myLabel.frame = CGRectMake(-1, -1, tableView.frame.width, 30)
myLabel.font = UIFont.boldSystemFontOfSize(14)
myLabel.backgroundColor = ClientConfiguration.primaryUIColor()
myLabel.textColor = UIColor.whiteColor()
myLabel.text = "Select Time Zone"
myLabel.textAlignment = .Center
let frame = CGRectMake(1, 1,headerView.frame.width , 70)
self.btnTimeZone.frame = frame
headerView.addSubview(myLabel)
headerView.addSubview(self.btnTimeZone)
self.buttonTitileString = self.selectedZone.value
self.btnTimeZone.setTitle(buttonTitileString, forState: .Normal)
return headerView
}
In horizontal mode the button text and label are aligned to left
and when i set self.btnTimeZone.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Center
its fine in horizontal mode but in vertical mode they all are right aligned as;
enter image description here
How can i solve this issue i need both of them in centre aligned in both horizontal and vertical mode.
You just need to reload the table when rotate the phone. Implement following method and inside of this method reload the tableView
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
tableView.reloadData()
}
In case of the application should support both portrait and landscape modes, the good approach would be to work with NSLayoutConstraint.
Of course you have both options to create them programmatically or from the Interface Builder, I'd like to note that you are able to create the header view as a cell, without the need of doing it programmatically; That's -obviously- will leads to the ease of setup the desired constrains for the header subviews.
Try this also
change
tableView.frame.width
to
tableView.frame.size.width
You could try to set autoresizing for parent view.
headerView.autoresizesSubviews = true
myLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.btnTimeZone.autoresizingMask = [.flexibleWidth, .flexibleHeight]
In Swift 5 (and 3, 4 too) you got to override viewDidLayoutSubviews() method of life cycle of view controller, it calls after viewWillTransition() method when rotating your device.
In viewDidLayoutSubviews() method you just need to reload the data of your tableView in order to redraw your section header for portrait to landscape or landscape to portrait, and it works perfectly.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.tableView.reloadData()
}
Thanks to GayashanK for give me this idea with his answer.

Trying to zoom a multilayer set of UIViews

Please point me in the right direction - I can find neither a solution nor a tutorial that solves my problem..
I have the following hierarchy of views in a ViewController:
UIView
ScrollView
Container
Drawing
Image
I can zoom in and out using a tap gesture, however, I don't want the pens in the drawing view to resize. I need to be able to draw lines on the image at a greater detail.
If I zoom the views separately, then the pens are out of sync with the image.
The views are setup in IB.
The code in ViewDidLoad to initialize things is as follows:
scrollView.backgroundColor = UIColor.black
scrollView.contentSize = imageView.frame.size
scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
tap.numberOfTapsRequired = 2
imageView.addGestureRecognizer(tap)
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 4.0
scrollView.delegate = self
And the zoom method is:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
I've tried starting the following alternatives:
scrollView.contentSize = drawingView.frame.size and
..
return drawingView
I've also set imageView as a subView of drawingView.
And finally, I've set both as subViews of the Container View (a UIView, not a UIContainerView.
I am conforming to the UIScrollViewDelegate.
Any help would be appreciated.

Why can't I change the view's frame size in Swift?

So this is the weirdest thing I came across ever.
I add a simple UIView on top of an UIView on an UIViewController. I change the size to 200 x 200 and then I want to change the UIView's size by placing this line of code inside the viewDidLoad method:
self.gameBackgroundView.frame.size.height = 10
which seems perfectly normal in Swift. Though, nothing happens. I can change the color, corner radius etc...
EDIT:
I have also deleted all constraints from that view and it still does not work.
Ok, So I found a solution here on stack ..
Change frame programmatically with auto layout
The correct answer, that works is, that:
I need to create an IBOutlet of my heightConstraint
Change the value of that constraint accordingly
Thank you all!
It is because of Auto Layout, however, you could do it after Auto Layout is done its work or change constraints of it. Set it your frame in your viewDidAppear() instead. It should work.
I hope this helps you.
Try this code, it will work on any device
let BackImage = UIImage(named: "backGrndImg#2x.png")!
var imageView: UIImageView!
override func loadView() {
super.loadView()
self.imageView = UIImageView(frame: CGRectZero)
self.imageView.contentMode = .ScaleAspectFill
self.imageView.image = BackImage
self.view.insertSubview(imageView, atIndex: 0)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.imageView.frame = self.view.bounds
}

Resources