I've got a view controller that handles a lot of complex on-screen controls. One of these is a sliding menu that contains 9 UIButton controls drawn in a grid using constraints, like so:
The load time of this view controller is nearly 3 seconds on device, and I've narrowed down the cause to the quantity of UIButtons inside this view. (I originally thought it was because it was being drawn off screen, but moving it to the center of the view controller didn't help).
I'm trying to come up with a way to improve the performance of these buttons, but I'm not really sure which direction to go. Will loading them in a UICollectionView help? Or is there a way to lazy-load the buttons so that they're drawn after the view controller is presented?
Turns out migrating this to a UICollectionView (even using constraints written in code) has made a significant performance improvement to this view controller.
It also has the added benefit of supporting paged views - more than 9 controls in the menu.
Related
I have an iPad app similar to the iPad Keynote with a narrow overview on the left and a paged UICollectionView of my "slides" on the right. The collection view is using the default FlowLayout. Some of these slides are standard PDFs and some are embedded UIViewControllers that have been scaled (with a CGAffineTransform) and embedded in the cell. I'd like to smoothly animate the overview sidebar offscreen and zoom the current page cell to fullscreen. The collection view should allow paged swiping at whatever size. I'm using storyboards and autolayout.
I think I need to simultaneously animate about three things:
The collection view constraints (to the sidebar) to enlarge/shrink it
The flow layout's sizeForItemAt: value
The CGAffineTransform on the embedded view controller.
I have some pieces working (a single embedded View Controller "slide" that scales correctly) but cannot get the collectionView/cell resize dance to work correctly. The cell resize animation is jerky, or ends up with the wrong offset, or works for the leftmost cell but not for other cells.
I've tried most of the suggestions in the answers to this question but with no convincing success. I can't believe it's impossible but at this point I'm considering the smoke and mirrors approach of animating a static slide and hiding it after the animation completes. The attached video - ignoring the glitches - illustrates the kind of effect I'm after:
It's worth noting, on close inspection, that Keynote cheats somewhat when it comes to swiping between slides in edit mode, and manually manages the next slide sliding onscreen, so probably doesn't use a UICollectionView.
Has anyone done anything similar, or have any suggestions for things to try?
I managed to solve this. There's a proof-of-concept GitHub repo here.
There are a few moving parts:
There are two pieces of UIView scaling code. I suspect these could be combined with suitable delegate references as the nested view controllers are embedded. The first piece scales (statically) correctly when the Collection View cell is created. The second is an animated scale/translate when the sidebar size is changed.
I added a FlowLayout subclass to remove flicker as the collection's layout is invalidated during scaling.
The sidebar-related transform in the top-level VC uses most of the tricks in the book - invalidateLayout(), performBatchUpdates(...), layoutIfNeeded() etc. as well as animating the contentOffset to the correct value. Some manual tracking of the correct page/slide is required.
There's still a slight flicker occasionally at the start of resizing. This may not be an issue with my particular colour-scheme which will be black on dark gray. Bonus points if anyone can suggest how to track this down or alleviate it.
I am combining what was previously two separate views into one unified view inside a UIScrollView. One of the subviews I am dealing with is a UITableView that is used to display user data in a visually appealing manner.
Here is how I would like the UI to look:
but when I build the app with this view the table disappears. When I move the table further up on the screen though it displays, but with weird dimensions:
.
I do not know what is going on here or how to debug it. Has anyone encountered this behavior before and know of a possible resolution?
Never mind, looks like I solved it. I embedded the UITableView in a UI view and set the layout rules for the UITableView to fill the parent view, and I then applied the layout rules to UIView to position it where I wanted.
I don't like being limited by the built-in screen navigation and storyboards are severely limited so I use this "core window" model I came up with long ago, where one window acts as a foundation. I load another view controller but load a nested UIView inside the main view, I call this the core and animate it over everything but the controls I want to remain onscreen, e.g. status bar and tab bar.
In the past I avoided auto layout because there were only two screen sizes, I just created one resource for each one. Now there are at least four and avoiding auto layout isn't an option. But when I do my nested view trick in XCode with auto layout turned on I can't see the controls in the nested UIView, infuriating, and the interface builder is very limited with AutoLayout.
Changing transparency, Z order, removing size classes, no joy. It's only putting the controls in the nested UIView back in the main view that makes them visible.
I can get around this by scrapping the nested view and making the view controller's main view free form, then coding the controls that AutoLayout doesn't handle well after viewDidlayoutSubviews is called. This works.
But I would really like to know why controls in nested UIViews are invisible in IB. They weren't before.
Edit: the loaded nested UIView does work at runtime.
For instance, say I wanted to load a view that had a table view controller, but only on the bottom half of the view. The top half might contain labels or buttons, etc. I am aware that there is a "SplitViewController" Class for the iPad, but how do you implement this on the iPhone? Thanks
On iOS4, you can put labels, buttons of the top half onto a topView(UIView), place the bottomView(UITableView) under it.
On iOS5, childViewController is supported, so you can also put them into two different UIViewControllers.
On iPad, both the native Photos app as well as Reeder use a "expand/collapse stack" technique. Initially there is a stack of items on top of one another, each angled a bit with different corners showing. When you interact with them, the stack expands into a full screen and the items are laid out in a grid. When you collapse them, they collapse back into a stack.
What's the best way to set up my views to do the same thing? Should I just have a bunch of UIviews (one for each item) and manipulate their coordinates/transforms with an animation, or is there something more to it? Any example apps with code?
(Note: I am not asking about the interaction to invoke expand/collapse, I'm only asking what's the most appropriate way to lay out and set up my items.)
These days, use UICollectionView with different layouts and transitioning between layouts.