Setting corner radius through viewDidAppear() or viewWillLayoutSubviews()? - swift

In summary, setting the corner radii to get round left and right edges for my UIButtons in my application works by grabbing the buttons bounds and dividing the height by two in viewWillLayoutSubviews(). However, if I navigate to another screen via UIBarButtonItem(), rotate the device, and then navigate back to the screen with the UIButtons() they are NOT round. The corner radii are still based on the button dimensions from the previous orientaion. I tried to use viewDidAppear, but there is a second/noticable delay in setting the corner radii.
Is there anyway to speed the process up of viewDidAppear? I don't think viewWillAppear will work because the view controller isn't aware of the default (square) dimensions of the uibutton(s) I am changing.
The application I am working on is this:
Screenshots of my current application from loading screen to the point of the corner radius not being updated correctly

Use viewDidLayoutSubviews instead, because you'll have the updated bounds at that point, but not yet in viewWillLayoutSubviews.
Or I might suggesting have a button subclass that does the rounding within its own layoutSubviews, freeing your view controller from having to iterate through buttons and rounding them.
For example:
#IBDesignable
class RoundedButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
let radius = min(bounds.width, bounds.height) / 2
layer.cornerRadius = radius
}
}
And then just use this class instead of UIButton. That yields:

Related

ARSCNView Corner Radius not showing

I have a corner radius on my ARSCNView as below;
override func viewDidLayoutSubviews() {
sceneView.layer.cornerRadius = 8
sceneView.layer.masksToBounds = true
sceneView.clipsToBounds = true
}
However, it is only showing when you enter app in background as illustrated below;
As soon as the app is in the foreground the corner radius goes back to 0.
Ive tried adding in ViewDidLoad & ViewWillAppear no success
I just tried with just
sceneView.layer.cornerRadius = 8
without masksToBounds and clipsToBounds and it worked for me.
If you're sceneView is inside another view or the root view of your view controller, check the background of that view and make sure it's something noticeable.
Maybe the sceneView itself is larger than the phones screen. Check the frame size or the layout constraints and make sure they are not causing the sceneView to stretch outside the phone screen edges.
I hope this answers your question.

Issues when animating a simple Container View

Here is the inital setup:
I have 4 constraints on the UIView...see image below.
When I go to animate it with
#IBOutlet weak var leadingCon: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
UIView.animate(withDuration: 2) {
self.leadingCon.constant = -100
self.view.layoutIfNeeded()
}
}
It slides it off to the side however...it also adjusts the bottom margin. It starts larger then needed and then animates down to the 30....not sure why.
Top Margin
Trying to perform an animation in viewDidLoad is pretty much asking for trouble. It's way too early. Your views are not even in the interface, so the user is not going to see any animation anyway. Plus, your views do not yet have any meaningful size / position! Wait until at least after viewDidLayoutSubviews so that your views can assume their initial position and size before you perform an animation. Even better, wait until viewDidAppear so that the user sees the initial position followed by the animation.

Scaling a sub classed UIView

I have created a subclass of UIView and am trying to scale and move the view from within its m file but am running into some problems. When I used the command:
self.frame = CGRectMake(self.frame.origin.x-10,self.frame.origin.y-10,self.frame.size.width/2,self.frame.size.height/2); the object moves location but does not resize (the view only contains a few UIImageViews). In the xib file of the sub class I have the options checked to Clip Subviews and to Autoresize Subviews but neither appears to happen. Any ideas as to why the view will not resize with this command and how I could get it to resize.
Resizing your view is not the same as scaling it. Think of your view as a picture frame. What you're doing above is moving the frame, and also moving the lower right corner (you're shortening the frame's wood bars) - but that does not automatically shrink the picture.
There are four ways of resizing a view with subviews:
Let the superview clips its subviews (by setting view.clipsToBounds = YES): Subviews do not resize or relayout, but only show in the area that is inside the frame.
Let the superview not clip its subviews (by setting view.clipsToBounds = NO): Changing superview size does not have any visual effect on subviews, they also show outside of the frame.
Give the subviews autoresizingMasks: The subviews do not change size, but they relayout according to their autoresizing mask (for instance, a subview may always stay 10 px off the lower right corner of the frame, or may always span exactly the width of the frame.) Note that this does not necessarily automatically scale subview content. Set subview.contentMode accordingly.
Scale the superview: By setting superview.transform = CGAffineTransformScale(superview.transform, 0.5, 0.5), you shrink the superview and all its subviews (you essentially zoom out). Note that this makes superview.frame undefined, which means you shouldn't use that anymore. It can also make things a bit blurry.
You could also "manually" change all the subviews, but that kind of defeats the purpose of having a nice view hierarchy.
As MishieMoo said, temporarily set the backgroundColor of your superview to something visible. This will very likely show you that your view is indeed changing.

How to auto rotate your own custom views?

I've learned that the best way to get graceful rotation is to set the auto rotation mask on the view that you want resize or move. This works fine if you're using SDK views like UILabel, but if you have your own custom view that uses the drawRect method it doesn't rotate as gracefully. In fact the only thing that happens is that it stretches whatever you drew in drawRect.
I've tried redrawing both before and after the rotation, but it doesn't give me that smooth rotation.
I looked at a UITextField auto rotating (flexible width) in slow motion and it follows the edge perfectly during the rotation. That is what I want my view to do, so how do I do that? My views jump to the right position either before or after the rotation.
The following line will make your UIView stretch the middle pixel only. If this is not your desired behavior I suggest you read the documentation for contentStretch to learn how to manipulate the values of the CGRect.
[self setContentStretch:CGRectMake(0.5, 0.5, 0.0, 0.0)];
I would guess that the UITextField you're looking at has at least three subviews, one displaying the left cap of the field's border, one displaying the right cap, and one displaying the middle, with autoresizing masks of "flexible right margin", "flexible left margin", and "flexible width", respectively. If you set up your custom view something like that, and make sure its autoresizesSubviews property is set to YES, then you should get the same smooth resize that the text field does.

Creating a UIView in Interface Builder that automatically centers itself when added as a subview

I created a UIView xib in Interface Builder and tried everything I could to indicate that the UIView should center itself, anchor itself at center, orient itself in central coordinates, etc. etc.
But whenever I add it as a subview in code, I also have to programmatically set its frame up with CGRectMake() or else it will always add to the top-left of its parent. The math to reframe it is pointless and ugly, so I presume I'm just not twiddling a bit in the IB inspector correctly.
Can anyone confirm this is possible, and if so, what I need to do in IB to accomplish this?
Why don't you just set .center of the subview just added, to be the point created by halving the width and height of the superview?
Either that or define the rectangle that view is going into with IB (I'm imagining a container view) and simply set the frame of the view you are adding to containerView.bounds (bounds is a position independent value and so x,y will be 0 while size will equal the container size.
Centering but maintaining size isn't possible in IB. Centering but maintaining margins to its superview is though.
You will have to override the layoutSubviews message or simply keep the calculation code you wrote.