Is clipsToBounds property necessary? - ios

I am doing an animation practice from Apple's tutorial. The task is do build a UI of a music player. Each of control buttons has a "shadow" view underneath it, which appears when button is pressed:
Here is my code in viewDidLoad():
background.layer.cornerRadius = background.bounds.width / 2
background.backgroundColor = .clear
The thing is that tutorial insists to also add a clipsToBounds property for each of shadow views:
background.layer.cornerRadius = background.bounds.width / 2
background.clipsToBounds = true
background.alpha = 0.0
When I run my code, everything works fine, and shadow views appear as circles. So why use clipsToBounds here, considering that view is clipping to bounds of itself? Am I missing something here?
And while it's in the code - is using .alpha property a better practice than changing backgroundColor to .clear and back for animation purposes?

Related

Problem: Background color of programmatic UI remains black

I've created the UI of a modal that pops up when you press a Tab Bar Item within a Tab Bar Controller. This is the first time that I've accomplished this programmatically, so there may be something that I'm missing here, but I can't seem to change the background color of the modal at all. More specifically, I'm trying to make the background transparent, but it appears in black when the modal is presented, no matter what color I change it to. I'm not sure that it matters that I've programmatically added subviews to the main view (for example, a UIView called "titleContainer"), but want to note this here just in case.
Below is part of what I have in my code:
override func loadView() {
view = UIView()
view.backgroundColor = UIColor.clear
view.isOpaque = false
titleContainer = UIView(frame: CGRect(x: 0, y: 0, width: 414, height: 180))
titleContainer.layer.borderWidth = 1.0
titleContainer.layer.borderColor = UIColor.darkGray.cgColor
titleContainer.layer.backgroundColor = UIColor.black.cgColor
titleContainer.layer.cornerRadius = 12
titleContainer.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
titleContainer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(titleContainer)
NSLayoutConstraint.activate([
titleContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
titleContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
titleContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
titleContainer.heightAnchor.constraint(equalToConstant: 180),
])
}
UPDATE: In addition to the fact that the original code was adding a color to the layer of the UIView, the modal was also sub-classing UITabBarController and not UIViewController, hence why the background color of the modal seemed to be inheriting that of the first VC in the Tab Bar Controller. Changing the superclass to UIViewController ultimately resolved this issue.
You're adding a color to the layer of the UIView. Remove the following line to get the view's background color. Or you can update the layer's color instead.
titleContainer.layer.backgroundColor = UIColor.black.cgColor
To set the color of the previous ViewController's view background you could set it while transitioning as follows:
viewController.titleContainer.layer.backgroundColor = view.backgroundColor?.cgColor
So your solution is correct the subclassing of your modal controller. In the future, you may want to double check the parent class of your subclasses especially when something off is happening like in your case.
And secondly, another way to help you debug the application is to toggle the attributes of your controller, say. a background color, and if you change your first tab screen's bg color, and the modal copies the color, then you can get to a theory that your modal is somehow getting that attribute from the first tab screen.
Lastly, utilize the Xcode's debugging features. One of those is Debug View Hierarchy. - This will give you the hierarchies of your views in 3-dimensional perspective.
Make sure to select overCurrentContext as modalPresentation for the vc
vc.modalPresentation = overCurrentContext
// present the vc
vc.bColor = UIColor.red
and declare this inside the vc
var bColor:UIColor!
Then set it here
titleContainer.layer.backgroundColor = bColor
Make you super view color to clear for your presenter view controller
self.view.backgroundColor = .clear
Than write this where ever you want to present your view controller
let controllerObject = yourControllor object from the storyboard
controllerObject.modalPresentationStyle = .overFullScreen
controllerObject.modalTransitionStyle = .coverVertical
present(controllerOject, animated: true, completion: nil)

Swift UIView Opacity Programmatically

I'm having quite a hard time messing with UIView's properties to achieve a desired opaque look programmatically that can be easily done through Storyboard and Attributes Inspector.
What I want to re-create (settings from attributes inspector):
A UIView with a background color of (RGB Sliders: 0, 0, 0) and Opacity Slider set at 75%, with alpha defaulted at 1. So basically a black UIView with the opacity toned down.
What I've tried programmatically:
1) view.backgroundColor = .black
view.alpha = 0.75
2) view.backgroundColor = UIColor.black.withAlphaComponent(0.75)
view.isOpaque = true
Attached is a picture of the UIView selected in Storyboard with the settings for you to see. If you need any more information, please don't hesitate to let me know. Much thanks for your help.
UPDATE: Thanks for all your input. The combination of Clever Error's explanation of view layers and Matt's code allowed for me to achieve my desired look.
Desired UI Look!
What you are describing is:
view.backgroundColor = UIColor.black.withAlphaComponent(0.75)
view.isOpaque = false
The view must not be marked opaque, as it is not opaque.
You can set opacity to view like below in Swift 3
view.alpha = CGFloat(0.1)
Summarizing these answers https://stackoverflow.com/a/40405424/7767664, https://stackoverflow.com/a/46669162/7767664
for UIView itself opacity
view.isOpaque = false
view.alpha = CGFloat(0.5)
for UIView Background opacity
view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
view.isOpaque = false
When your app runs, the view hierarchy will be
UIWindow
UINavigationControllers view
Your View Controllers View
The problem is that UIWindow is black by default, and the UINavigationControllers view is clear. So it ends up mixing your transparent black color with full black to get just black.
You would need to add another view to your view controller that is transparent black then set the view controllers view color to the one you want to blend with.

Expanding UiView Animation

I am trying to implement the following animation in my swift iOS app. There is currently a UIView at the bottom of my screen with the following properties :
let containerView : UIView = {
let this = UIView(frame: CGRectMake(0,0, 600,150))
this.backgroundColor = UIColor.clearColor()
this.layer.cornerRadius = 5
this.layer.borderColor = UIColor(red: (69/255.0), green: (209/255.0), blue: (153/255.0), alpha: 1.0).CGColor
this.layer.borderWidth = 0.5
return this
}()
Inside, there is an imageView, a couple buttons and other components. The containerView also has a blur effect implemented on it. When the user presses on it, I want the view to move upwards until it reaches the top of the screen. At the same time I want the borders to be drawn, to fill the whole screen, as shown in the outline below. I also want to apply the blur effect as an animation along with the border to the whole screen. Finally, when this animation is finished, I want my collectionView to fade into the space which has been created within the expanded view. I have next to zero experience with animating views in Swift, however these are the ideas which I had :
Apply a movement animation which moves the top of the view from the current position to the top of the screen.
During this process, gradually fade in the expanded view so that it appears as if the view itself is expanding.
Finally, when both animations complete, fade in the collectionView (this should be the easiest part).
However, I'm not sure if my way of thinking is correct, particularly when it comes to drawing the borders and background dynamically doing the animation. I am looking for some advice on how to approach this problem.
Take outlet of heightConstraint of the view which you want to animate.
Make heightConstraint.constant = 0 initially.
On click do something like this.
UIView.animateWithDuration(0.3) {
self.heightConstraint.constant = YOURMAXVALUE
// perform fade in out tasks here
self.view.setNeedsUpdateConstraints()
self.view.layoutIfNeeded()
};
or you can do this with topConstriant also..
Initially set topConstaint such that view will go down.
And then animate like this to see effects

Avoid status bar transparency while animating

I got the viewController with 2 elements:
view with labels and buttons
tableView
I'm getting the following animation by changing view's height constraint from 170 to 0 and than animating view.layoutIfNeeded() and tableView.layoutIfNeeded().
My goal is to hide menu when content offset of the tableView reaches some value.
This works fine, except I got an overlay of status bar over the moving content from my view. Are there any options to add a sublayer to status bar not to be transparent? Or any other suggestions?
Thanks!
Create a view, put it where the status bar will be, and set its background color to which ever color you require. For example:
let statusBarView = UIView(frame: UIApplication.sharedApplication().statusBarFrame)
statusBarView.backgroundColor = UIColor.blackColor()
view.addSubview(statusBarView)
Or, set the content edge inset by (20.0, 0.0, 0.0, 0.0), which I would agree is a much more elegant solution, as suggested by #holex in the comments

Draw border "within" UIViewController

I need to draw a visible border that goes around the edge of the screen within my view controller. I tried setting the view's borderWidth and borderColor, but nothing appeared on the screen. How would I accomplish this?
I tried the following code and it worked.
self.view.layer.borderColor = UIColor.orangeColor().CGColor
self.view.layer.borderWidth = 3

Resources