Making UIScrollView (and contents) opaque - iphone

I'm trying to speed up my UIScrollView and one method I know of is to set everything to be opaque. I think I have done so, to my UIScrollView, its contentView, the contentView's tiledLayer (I have a CATiledLayer as the actual useful bit that the users see), and on the UIView that all of this sits in. But despite all of that when I look it through the Core Animation instrument with 'Color Blended Layers' turned on the scrollview's contents are shaded red showing they are transparent. The only green bits are outside the bounds of the contentview (which I can only see when it pans out to the side and then bounces back).
Is there something built in to ScrollViews, or CATiledLayers that could be ignoring 'setOpaque:' or have I messed up my view hierarchy and left something not-opaque?

To answer the question "Have I messed up my view hierarchy and left something not-opaque?", from https://developer.apple.com/library/ios/technotes/tn2239/_index.html:
UIView implements a useful description method. In addition, it implements a recursiveDescription method that you can call to get a summary of an entire view hierarchy.
So, call -recursiveDescription on the topmost view, and check each subview for opaque = NO;.

Related

Unable to get the correct frame for UIViewControllerAnimatedTransitioning to UIPageViewController

I have been battling this transition animation and I am pretty much out of ideas. I am attempting something similar to going from the collection to the individual photos in the Photos app on iOS.
It all works to my satisfaction with the exception that the frame for the "big" detail view of the image is not correct. It is the right size but it is about 87 points closer to the top of the screen compared to the actual position of the image in the final state. This is pretty much the same height as what is above the "safe area" (iPhone X titles + navItem) and irritatingly close to what is also below the safe area (toolbar and iPhone X home area).
I have Googled (and "SO'd") a bunch of different solutions to similar sounding problems. E.g: UIViewControllerAnimatedTransitioning with Safe Area Insets on iPhone X
I have downloaded and perused example code from Github. E.g: https://github.com/SamStone92/CustomTransitions
It seems to me that I have something in my view (controller) hierarchy which is complicating this more than most. I would love some hints as to what might be causing the problem and how I might go about fixing it.
My hierarchy is:
NavigationController containing the root VC with a UICollectionView.
Tapping a cell transitions to a UIPageViewController for a "detail view" where I can page between items in the collection.
UIPageViewController has a bottom toolbar in addition to the navigation bar.
The content ViewController has a ScrollView with a UIImageView in it to get some zooming.
Seems like the common approach is to add the destination view to the container, force a layout pass and then get the frame. I have tried many variants of this with and without converting the coordinates. (they appear to always remain the same before and after conversion)
My Theory
I am leaning towards the UIPageViewController being the complicating factor. But I have not been able to untangle how to get the correct coordinates.
The destination view (in the animation) is not the content view but the PageVC view which in turn may or may not have added the content view, adapted it to the navigation item or the toolbar.
Seems like viewWillAppear on the content VC does not have the right coordinates. I can tell that the detail content view is getting a call to viewWillLayoutSubviews after that and also after all the animation delegation stuff has had its turn.
This is a color overlay of my main views. Grey is the top and bottom areas outside the safe area. Blue is where the transition animates to before revealing the green, underlying actual position it should have animated to.

UIView does not display subviews

We created a UIView in a ViewController as a grouping mechanism. Now it turns out for some reason that it does not work as the subviews within it are not drawn (and this is without setting any of the other settings hidden etc.).
I've looked through the documentation and stack but I can't find anything about it. Am I missing something basic in the draw cycle?
See the image below:
The stuff in blue does not display at all and is a subview of View. I moved the yellow out of its subview and normally within the ViewController and that does display now.

Keeping UIViews visible only within a limited area of the screen

Is it possible to make a UIView only appear inside a limited area of the screen, especially while animating? (When it reaches the boundary, it should simply cut off at the boundary point, as if it were being obscured by an object in front of it.) I need this because I have a roll-out menu comprised of UIButtons, and I don't want the menu to extend beyond the edge of the toolbar when closed. Thank you!
(Alternatively, hiding the entire UIView upon reaching the boundary would also be acceptable. I just don't know how to check for this condition without continuously querying the center property.)
You can define a clipping area for your UIVIew using the clipsToBounds property. If you are using CoreAnimation to animate your view, you may want to have a look a the maskToBounds property of CALayer objects as well (each UIVIew has a layer property of type CALayer).
From the UIView Class reference:
Normally, a subview’s visible area is
not clipped to the bounds of its
superview, but in iOS you can use the
clipsToBounds property to alter that
behavior.

Unable to add oversized button in UIToolbar

I have a UIToolbar in IB with a custom UIBarButtonItem that is set to an image. The image height is larger than the UIToolbar height. The image does not load for some reason. Attached is a screenshot.
You should avoid using subviews that are larger than the parent view - even if it does work and draws the view outside of the bounds, you cannot always count on it because the clipping is skipped for performance reasons and depending on the drawing order the overlapping part of the subview might be covered later. Second problem is that only the part within the frame of the superview is able to handle the touch events.
As to why you don't see your image, it's probably a different problem, I doubt it has something to do with it going outside the frame. Post your code to get more feedback ;)

UIScrollview with two images - Keeping 1 image zoomable and 1 image static (fixed size)

I have a UIView which contains a zoomable UIImageView and also another semitransparent UIView on top of that.
What I am trying to achieve is to be able to zoom the UIImageView while keeping the semitransparent view static and not zoomed.
If I add the semitransparent UIView on top of the UIImageView (which is added to the UIScrollView), everything zooms. However, if I add both as subviews to the base UIView, the touches only get tracked is the semitransparent UIView since its the last one added.
I do need control to reside first at the semitransparent UIView for the touches since I may want to resize the semitransparent view. However, I'd like to pass control of the touches to the UIScrollView if two fingers are used. Is there anyway for me to achieve this? The nextresponder doesn't seem to work. I also tried to use hittest in addition to subclassing UIWindow, but the base UIView needs to push/pop navigation controlling ability so I don't think I can subclass UIWindow to push onto the navigation stack.
Any help would be appreciated.
Thanks,
Winston
Hm.. you can try this hierarchy (possibly subclasses):
UIView (container)
> UIView (semitransparent overlay)
> UIScrollview
- UIView (zoomable content)
Like this, the overlay does not scale.
The tricky thing then is the user interaction on multiple layers. Its easy if there are areas in your overlay that should not detect user touches, for that you just set the UIView property 'userInteractionEnabled' to 'NO' for the view parts where touches should be 'forwarded' to the underlaying layers.
But if I get you right, you need something more complicated. You probably could set up some kind of master-touch-controller in the container UIView, that finds out what is happening and then calls certain methods of its subviews / forwards the events.
I don't know all the exact methods you need to override/implement in the container, but check out the tapZoom demo from the ScrollView Suite sample code. It's a pretty nice example there.
Just out of curiosity, may I ask what this interaction model is used for?