iOS Modifying CALayer Using View Attributes After Constraints are Applied - ios

Say I have a UICollectionViewCell (applies to any view however) with a UIImageView (again, any view) and I'm not using auto-layout. I want to apply a CAGradientLayer on top. Inside the awakeFromNib I could use the frame.size of the image view to create a bezier path for my shadow. This works great!
The problem is if I use auto-layout constraints to size and position that image view inside the collection view cell. Constraints aren't applied at the awakeFromNib callback point. So I can't use the first approach. My solution thus far has been to defer that CALayer positioning to layoutSubviews. This is not an optimal solution because it is called multiple times and you can actually see the CALayer reposition itself.

Related

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.

Auto-Layout UIScrollView and an animated UIView

Currently having an issue with using auto-layout and UIScrollView. The issue is when I scroll down on the scroll view, a previous UIView (that should be free roaming, and is animated to various positions) gets set back to its initial location where it is located in Storyboard.
What's the best way to make my single UIView not follow the behavior of auto-layout and let it do whatever it wants to do?

Rotations in iOS if UIViewAutoresizing doesn't cut it

I'm creating a view controller that has non-trivial rotation behavior. I can't find a way to get all my transformations to occur with only UIViewAutoresizing (I'm doing things like keeping by bottom bar at the same "absolute value" on the screen" while rotating buttons). What's the correct way to handle these type of rotation behaviors? Is there a way to disable auto resizing for a specific view and handle the rotations yourself?
If you set a view's autoresizesSubviews property to NO, that view will not apply autoresizing to its subviews. You can do this in a xib or storyboard by unchecking the “Autoresizes Subviews” checkbox in the attributes inspector.
The correct place to programmatically lay out subviews is in the layoutSubviews method of your custom UIView subclass. Your view will receive the layoutSubviews method whenever its size changes or when its subviews array changes. You will receive it when the view is first being put on the screen, and inside the autorotation animation block.

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