In this view
there are multiple subviews. Now I configured the views to drop a shadow as shown in the screenshot: The views are dropping the shadow also over the other views. Do you see a way to easily drop the shadow behind all views? So z-index of all the shadows < z-index of all the views.
I already tried to create an additional view for each box and placed all of this shadow views behind all boxes. This kind of works. But there is a lack when moving the boxes around using a PanGesture. Also this design looks a it messy. At the moment, it's a clear design to have one UIView for each box.
You're thinking about the solution wrong. However in your own words, 'behind all views' is the answer.
As you noticed, applying a shadow to each view will have overlapping shadows due to each views z-index.
You mentioned creating an additional view for each box which is close to another solution but not quite. You could create a single container view and place all of the boxes inside this one container view. Then apply your shadow to the container view. This will give you your result, but will have horrible performance! Every time layoutSubviews is called, such as when a views frame changes, the shadows are recalculated. As you mentioned, you're using a pan gesture, so moving a box slightly will layout the subviews a few dozen times.
The solution you should go with is to create 2 container views which are sibling views. For every colored view you create, add it to the top container view and create another view which will be added to the bottom container view, lets call it the shadow container view. Use constraints on the views inside of the shadow container so their top, leading, bottom and trailing are equal to their equivalent view in the top container view. Next add a shadow to the views inside of the shadow container view and make sure to apply the layer.shadowPath! This shadow path is the key to prevent the shadow from being redrawn when you pan.
If you don't understand and need an example let me know and I'll give you one.
Hey Chris, Try this
yourView.layer.shadowColor = UIColor(white: 0.0, alpha: 0.5).CGColor
yourView.layer.shadowOffset = CGSizeMake(0.0, 0.0)
yourView.layer.shadowOpacity = 1.0
yourView.layer.shadowRadius = 6.0 //increase the width & height of shadow
You can simply add views with shadow first then add your actual view above them. Or, you can try to alter the zPosition of layer of all the view after setting shadows.
Related
I want to know whether a specific portion of a UI view can be made hidden.I have a view that is movable.The problem is that when I move the view down the view is visible below safe area.I want to hide the portions of the view that are below safe area.
If you constrain the enclosing view, lets call it simply view, of that movableView to the safeArea, the easiest way would be to simple set:
view.clipsToBounds = true
This will prevent drawing any of the view contents outside of its bounds. So if movableView is its subview somewhere in the hierarchy, and its part moves out of the bounds (i.e. below the safeArea), the part outside will be clipped and not rendered.
If not don't have such a view yet, adding a transparent view (backgroundColor = UIColor.clear) that would be constrained as such with its clipsToBounds set to true would solve it for your.
Normally developers try to bring subview to front. On contrary, how does one bring superview to front?
I'm looking for a reverse of bringSubviewToFront(_:). It should look like bringSuperviewToFront(_:)
I'm looking for a reverse of bringSubviewToFront(:). It should look like bringSuperviewToFront(:)
That doesn't exist. Instead of giving your button a subview, make both the subview and the button subviews of some container. Then you can adjust their relative z positions to suit your purpose.
I do not think you can do that. Views are laid down in layers with each sub view layer being part of super view layer. The effect you want to materialise can be achieved by hiding/removing all the sub views of the view you want to get Bring To Front effect on.
This works well with sub views because normally you would want to show/hide subviews inside same parent view based on their layer position!
In the spirit of being less rude.
func bringSubviewToFront(view: UIView) {
let superview = view.superview
superview?.addSubview(view)
}
That will bring it to the front. As in:
bringSubviewToFront(mySubview)
What the above code does is detach the view from wherever it is in its superview's hierarchy and reattach it to the top of all the subviews. This has the effect of bringing it to the front like you want. If the view isn't part of a hierarchy, then the function does nothing.
I was wondering how to make a popup window similar to this example:
The origin window is full of buttons that when is selected will then pull up the image I desire to use.
I would simply create a reusable UIView component and everything you need as a subview, such as a UIImageView for your image, a UILabel or a UIButton in the top right. Here is the process to show it:
Create a UIView that takes up the full screen, make it black, and maybe 0.5 alpha.
Create another UIView which is your primary pop-up view, make it slightly smaller than the previous view, but make sure both of these views are subviews of the parent subview.
Add the desired elements on to the pop-up view as subviews, I would even suggest creating a UIView subclass if you plan to use this a lot.
To present the pop-up, make sure both views are set to hidden = true when created and so that when a button is selected, you can set them to hidden = false
If you would like them to be animated, simply start them off with alpha = 0.0 and use something like UIView's animateWithDuration and set the pop-up view to alpha = 1.0
There is a lot of little details you can change to cater to your needs, but this is the basic structure on how to accomplish your goal.
Check out UIView animation methods here.
I have an image on my view, which I add programmatically & and not through storyboards. The image gets animated to move up the screen. At one point it crosses paths with several buttons and labels, which contain important text that gets blocked by the image passing over them. I want the image to move under the labels and buttons so that the text remains visible. Based on this answer IPhone Interface Builder: Z-Index, Z-order of a button, image, ui element, etc?, I tried to use editor => arrange => sendToBack/sendToFront, however, I don't think this is having any effect because the image doesn't appear in the tree of elements in the storyboard. As noted, it gets added programmatically at a certain time. Is there a way to do this?
I believe you can use [view insertSubview:imageView atIndex:0] which will place it behind all other subviews. Depending on what other subviews you have, you may need to increase the index as it controls what is placed over what in the view (lower index will go behind higher index)
As in answer to this question: Difference between addSubview and insertSubview in UIView class
If you're using addSubview:, your view will be placed on top. To control it's depth use either insertSubview:atIndex: (at exact place from bottom) or insertSubview:aboveSubview: or insertSubview:belowSubview: (which places new view above/below another known object in view hierarchy).
I created a container view that holds a bunch of child views - a collection view, a custom toolbar and some bits and pieces.
The design has a border on the top, left and right sides, but not the bottom, so I overrode drawRect to include border.
When I added the toolbar I noticed that it appears over the top of the border. (For some reason I initially thought it wouldn't but of course it does!).
Is there anyway I can tell drawRect to draw over the top of my subviews?
Of course there's loads of other ways to solve my problem (adjust the toolbar's frame for example) however I'm asking this question in order to get a deep understanding of how drawing works in relation to compositing and the view hierarchy.
Drawing happens beneath all subviews of a UIView. Think of it as being on the very base - an actual part of your view - and then each subview is added on top of your view. To make the drawing above the subviews is the same as wanting for the subviews to appear under the view, while still being subviews. Perhaps that analogy makes it clearer why it must always be on the bottom. And it also leads you logically to the solution:
To get the drawing to appear above subviews, simply create a new UIView subclass to place the drawing code inside, and place this above all other subviews.
It might also be a good idea to override your UIView's addSubview: implementation, to ensure your subview always remains on top.
I believe you can't, since the drawRect is called first for the view and when it has finished drawing drawRect is called for subviews to draw over it. Maybe just make another subview on top of that view that has the borders you need and is transparent everywhere else?
Subviews are drawn on top of their super views. So the answer to your question is no.
At the time when you draw the border on your container view, Cocoa hasn't even started drawing the toolbar yet.
I guess you could make the top of the border a subview or move the toolbar down a bit.