UIStackView layer property - ios

Every view has a layer that does the rendering. What confuses me is that you can't set the corner radius or border to the stack view, yet when you hide one of the arranged subviews the rest of them fill up the stack view.
Furthermore, Apple doc says that the stack view only manages its arranged subviews.
But, how does the stack view resize its subviews? Does the stack view's layer do the resizing when an arranged subview is hidden? If not, what is then the usage of the layer property in a stack view?

The UIStackView is a nonrendering subclass of UIView; that is, it does not provide any user interface of its own. Instead, it just manages the position and size of its arranged views. As a result, some properties (like backgroundColor) have no effect on the stack view. Similarly, you cannot override layerClass, draw(:), or draw(:in:).
consider placing the stack view inside another UIView and giving that view a corner radius or border.
Apple Doc

Related

Swift: Bring View from Stack View to front

I got a Stack View with view: 1,2,3,4 and 5
Looking for a method to bring the Image View4 from view4 in the Stack view, above all the other views. The reason I need this is because I am moving the Image View4 over the Image View3 in view3.
I have tried to move view3 over view4 in the view hierarchy, but that just swaps their places in the Stack View.
From the UIStackView documentation:
The order of [the views in] the subviews array defines the Z-order of the subviews. If the views overlap, subviews with a lower index appear behind subviews with a higher index.
So since all views in the stack view's arrangedSubviews array are also in the stack view's subviews array, you should be able to use the standard UIView APIs to rearrange the views z-order:
bringSubview(toFront:)
sendSubview(toBack:)
exchangeSubview(at:withSubviewAt:)
I don't know whether this is possible to do in Interface Builder or not.
Remove the image from the stack view and add it to the same view that contains the stack view as a subview, using addSubview(_:). That will put it on top of all other views. You could also use insertSubview(_:aboveSubview:) to insert it directly above the stack view.
You'll need to add constraints to the new view so that it is positioned where you want it.
You can have IBOutlet property in UIViewController but in view hierarchy it is placed in UIStackView.
So you should use
stackView.bringSubviewToFront(myView)
rather then
self.view.bringSubviewToFront(myView)

Why is my UIView drawing behind my other views?

I have a UIView which is opened and closed by a button onscreen. I am positioning it over a scrollable custom text area which is a bunch of UILabels added to a UIScrollView.
I've made sure that it is added last in my view hierarchy, in the xib. I have also tried calling bringSubviewToFront, and have even removed the UIView from the parent view and re-added it after doing the layout.
Nothing that I have tried prevents it from being drawn behind this UIScrollView. I have verified that my UIView is actually the last UIView in the hierarchy by looking at the view hierarchy in the debugger at runtime.
The UIView in question, shown as a smiley in the picture here, has children. It has a 3x3 grid of invisible UIButtons, and a UIImageView to draw the image, which is normally something other than the smiley. But I am operating on the parent UIView, not the children.
Is there anything I can try, to help diagnose this? To recap, I have done all the following:
the UIView is added last in my view hierarchy, after the UIScrollView. It is a child of the same parent (the root view) as the scroll view - hence, a sibling view of the scroll view.
after doing the layout, I've tried [self.view bringSubviewToFront:myView]
after doing the layout, I've tried doing [myView removeFromSuperView] followed by [self.view addSubview:myView].
The latter two operations are performed at the very end of my layout method.
Any ideas?

Hide non child UIView in UIView

I want to hide a non child UIView in a UIView but I don't know how to do it.
To be specific, I have a UITableView. Each UITableViewCell has another view inside it (a wrapper view called wrapperView). The wrapper has some labels set up in IB and some created programmatically. I have created a custom slide mechanism that reveals buttons under the wrapper (like the standard one does).
The labels created programmatically don't exceed wrapper's bounds because it clips the subviews. The problem is with the labels created in IB. They are the subviews of contentView.
How can this be solved? Is there a way for a UIView to clip other views on the same level(not parents nor children)? Or "transfer" the labels to the wrapper view?
It isn't completely clear what you're asking. A view will only clip it's subviews, not views that happen to fall within their frame rectangle but aren't subviews.
If you want to move a view object from one view hierarchy to another you can use addSubview(_:) to do so. That will automatically remove it from it's current parent view. To quote the Apple docs:
Views can have only one superview. If view already has a superview and
that view is not the receiver, this method removes the previous
superview before making the receiver its new superview.

UIStackView inside a subview programmatically

I've got a ViewController that has a lot of labels that must be displayed horizontally, so I've decided to use UIStackView for this.
These labels belong to different "sections", so I'm using nested stack views to achieve this. The problem is that one of these "sections" should be displayed with a different background color than the others.
I've read in another thread that UIStackView does not have a background color, and I should add the stack view inside a UIView and set a proper background color to it.
What I've made so far:
Create a UIView and set its color
Create a sub stack view and add some labels to it.
Add the sub stack view to the colored UIView
add the colored UIView to the main stack view.
The result: I'm not seeing any of those views inside my view controller.
Note: I need to do this programmatically.
Thanks in advance!!

How can I place a non-scrolling UIView underneath the scroll indicators on a UIScrollView?

I have an application where I'm using a zooming scrollView to do image cropping to a rectangle with a fixed aspect ratio. I have a mask where I darken the parts of the image that will be cropped. Currently I add this subview to the UIScrollView's parent, making them siblings, where this mask is 'higher' than the scrollview. Looks great. Except...
This mask is also masking the scrollIndicators and therefore looks a bit dumb. I could turn off the scrollIndicators, or, ideally, I'd like to place this UIView underneath the scrollIndicators, but not get scrolled with other content, which is what would happen if I made it a subview of the scrollview via [scrollView addSubview: myMaskView];
Anyone know if this is possible?
First, subclass UIScrollView so that you can modify the default behavior of scroll view.
Second create an image view with your image, and put both the image view and your mask view to a scroll view, this way your views will be underneath the scroll indicator.
Third, in your scroll view delegate method viewForZoomingInScrollView:, return your image view, so that only the image view zooms. Note that the scroll view will adjust the content size to be the size of the returned view, but it's fine as long as your image view takes up the whole content size.
And last, override layoutSubviews method, move the mask view to visible bounds of scroll view. The layoutSubviews method is said to be called every frame of scrolling, so the position change won't be visible to end user.
For more details you can refer WWDC session video "Advanced ScrollView Techniques".
EDIT: OK, just found that you can avoid overriding layoutSubviews by implementing the delegate method scrollViewDidScroll.

Resources