Transition between two UICollectionViewCells - ios

I've got a UICollectionView using a flow layout.
Initially it shows small cells, roughly 5 X 5 on the iPad screen.
What I want to do it smoothly change to a nearly full screen cell size, with a cell with a larger, slightly different layout.
----------------
| |---| |---| |
| | | | | |
| |---| |---| |
| |
| |---| |---| |
| | | | | |
| |---| |---| |
----------------
transitions to..
----------------
| |---------| |
| | | |
| | | |
| | | |
| |---------| |
| |
| |---------| |
----------------
At the moment I use use a boolean showLarge which I set to YES when the user clicks (didSelectItemAtIndexPath)
Then I reload the data.
self.showLarge = YES;
[self.collectionView reloadData];
In my cellForItemAtIndexPath I load the appropriate cell according to the boolean:
if (!self.showLarge)
{
SmallCell *smallCell ..
etc
return smallCell;
} else
{
LargeCell *smallCell ..
etc
return largeCell;
}
However, this is an abrupt transition.
How would I smoothly animate to the new custom UICollectionViewCell?

You could use a different UICollectionViewFlowLayout, then change the collection view's layout on the fly. That'll give you a nice animation without the need to reload anything.

Related

UIPanGesture does not scroll parent UIScrollView

Layout situation:
I have a UICollectionView with multiple cells (arranged as a pager).
A cell contains a full size UIScrollView (A) with content size is equal to it's frame size.
This scroll view contains a second UIScrollView (B) with a content size larger then its frame size, means it is scrollable.
The problem is that a UIPanGesture issued in the inner scroll view (B) does not issue paging on the UICollectionView when the pan gesture hits the bounds of the inner scroll view (B).
I already figured out that this is because of the scroll view (A) is not scrollable because its frame size equals the content size.
Any idea how to achieve paging/scrolling on the collection view when a pan gesture is issued on the inner scroll view (B)?
I cannot replace the scroll view (A) as the scroll view is needed when the device is rotated.
UICollectionViewCell
------------------------------------------------------------
| ----------------------------------- |
| | UIScrollView (A) | |
| | (ContentSize = FrameSize) | |
| | | |
| | ------------------------------- | |
| | | UIScrollView (B) | | |
| | | (ContentSize = FrameSize * 2) | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | ------------------------------- | |
| | | |
| | | |
| ----------------------------------- |
------------------------------------------------------------

Flexible layout using interface builder

I want to achieve this layout that will resize width in landscape mode and will keep all spaces(gaps) as defined. So single column of UITextView in one row there are two which should take half of the width left when left right and in between gaps are deducted.
+---------------------------------------------+
| <y> |
| +-----------------------------------+ |
| | | |
| +-----------------------------------+ |
| +-----------------------------------+ |
| | | |
| +-----------------------------------+ |
| +----------------+ +----------------+ |
|<x> | 50% | | 50% | <x>|
| +----------------+ +----------------+ |
| +-----------------------------------+ |
| | | |
| +-----------------------------------+ |
| |
+---------------------------------------------+
I tried for a long time checking different constrains like width <= 280 and width >= 280 - both with the same results.
Can someone write step by step what to do to have this layout? Does it matter that it is inside the UIScrollView?
The structure is:
View
Scroll View
Content View
Round Style Text Field
Round Style Text Field
View
Round Style Text Field
Round Style Text Field
Round Style Text Field
Add an other view around what you want to center.
+-----------------------------------------------+
| <y> |
| +-------------------------------------+ |
| |+-----------------------------------+| |
| || || |
| |+-----------------------------------+| |
| |+-----------------------------------+| |
| || || |
| |+-----------------------------------+| |
| |+----------------+ +----------------+| |
|<x> || 50% | | 50% || <x>|
| |+----------------+ +----------------+| |
| |+-----------------------------------+| |
| || || |
| |+-----------------------------------+| |
| +-------------------------------------+ |
| |
+-----------------------------------------------+
It's easy to center a view within another view.
View
Scroll View
Content View
View
Round Style Text Field
Round Style Text Field
View
Round Style Text Field
Round Style Text Field
Round Style Text Field

Achieving Grid Layout of Buttons with Autolayout

I am trying to achieve a layout of buttons very similar to Apple's inbuilt Calculator app:
I am using autolayout to position the buttons, and drawing a 0.5px border on each button, aiming for a 1px gap between buttons (like the calc app, closeup showing pixels above, from a retina device).
Border applied by :
btn.layer.borderWidth=0.5f;
btn.layer.borderColor=[[UIColor blackColor] CGColor];
and the layout is set up using Interface Builder.
It almost works; but there is some variability in the gap between buttons - for example the gap between the "1,2,3,thru" row and the "4,5,6,and" row is 2 pixels, but the gap between the "7,8,9" and "cl,0,#" rows is only one pixel.
Constraints are :
Top black area has a fixed height
All buttons same height
In the numeric rows, numeric buttons are set to same width, THRU, AND, ALL OFF and ENTER buttons are set to same fixed width
Top row of buttons pinned to bottom of black area, bottom row pinned to bottom of superview
In IB the buttons are all positioned butting up against each other.
In interface builder and at runtime I don't see any autolayout errors; and a debugger dump of the autolayout info gives me:
po [[UIWindow keyWindow] _autolayoutTrace]
*<UIWindow:0x10908a560> - AMBIGUOUS LAYOUT
| *<UILayoutContainerView:0x109136140>
| | *<UINavigationTransitionView:0x10908ef80>
| | | *<UIViewControllerWrapperView:0x109138870>
| | | | *<UIView:0x1090e6d10>
| | | | | *<UILabel:0x1090d5bb0>
| | | | | *<UIButton:0x1090d27e0>
| | | | | | <UIButtonLabel:0x1091c9190>
| | | | | *<UIButton:0x1090844c0>
| | | | | | <UIButtonLabel:0x1091c7990>
| | | | | *<UIButton:0x109088b60>
| | | | | | <UIButtonLabel:0x1091c6190>
| | | | | *<UIButton:0x1090e2ce0>
| | | | | | <UIButtonLabel:0x1091c4990>
| | | | | *<UIButton:0x1090e4e50>
| | | | | | <UIButtonLabel:0x1091c3190>
| | | | | *<UIButton:0x1090db730>
| | | | | | <UIButtonLabel:0x1091c1990>
| | | | | *<UIButton:0x109068f50>
| | | | | | <UIButtonLabel:0x1091c0190>
| | | | | *<UIButton:0x10906db80>
| | | | | | <UIButtonLabel:0x1091be990>
| | | | | *<UIButton:0x1090d23a0>
| | | | | | <UIButtonLabel:0x1091bd190>
| | | | | *<UIButton:0x1090c8520>
| | | | | | <UIButtonLabel:0x1091bb990>
| | | | | *<UIButton:0x1090c9090>
| | | | | | <UIButtonLabel:0x1091ba190>
| | | | | *<UIButton:0x1090c5680>
| | | | | | <UIButtonLabel:0x1091b8990>
| | | | | *<UIButton:0x1090d7fa0>
| | | | | | <UIButtonLabel:0x1091b7190>
| | | | | *<UIButton:0x1090cc820>
| | | | | | <UIButtonLabel:0x1091b5990>
| | | | | *<UIButton:0x10909dda0>
| | | | | | <UIButtonLabel:0x1091b4190>
| | | | | *<UIButton:0x1090c8090>
| | | | | | <UIButtonLabel:0x1091b2990>
| | | | | *<UIButton:0x1090c8e30>
| | | | | | <UIButtonLabel:0x1091b1190>
| | | | | *<UIButton:0x1090d5390>
| | | | | | <UIButtonLabel:0x1091af990>
| | | | | *<UIButton:0x10d30d260>
| | | | | | <UIButtonLabel:0x1091ae190>
| | | | | *<UIButton:0x10909a6a0>
| | | | | | <UIButtonLabel:0x1091ac990>
| | | | | *<UIButton:0x1090cca40>
| | | | | | <UIButtonLabel:0x109161160>
| | | | | *<UIButton:0x10d30ea90>
| | | | | | <UIButtonLabel:0x109156460>
| | | | | *<UIButton:0x1090da9e0>
| | | | | | <UIButtonLabel:0x109177ad0>
| | | | | *<_UILayoutGuide:0x1090e6dd0> - AMBIGUOUS LAYOUT
| | | | | *<_UILayoutGuide:0x1090ce080> - AMBIGUOUS LAYOUT
| | <UINavigationBar:0x10907da60>
| | | <_UINavigationBarBackground:0x109087240>
| | | | <_UIBackdropView:0x1090899f0>
| | | | | <_UIBackdropEffectView:0x10908b110>
| | | | | <UIView:0x10908bbb0>
| | | | <UIImageView:0x1090877a0>
| | | <UINavigationItemView:0x10916bc30>
| | | | <UILabel:0x10917f810>
| | | <UINavigationItemButtonView:0x1090ee060>
| | | | <UILabel:0x1090ee5d0>
| | | <_UINavigationBarBackIndicatorView:0x109098c80>
Can anyone offer any hints on how to achieve a "pixel perfect" layout like this with Autolayout? Or should I be doing this programatically instead?
Layer borders are drawn inside the views bounds, so you aren't going to see a "gap" between the buttons, but the effect of two borders abutting each other. This isn't going to work in the non-retina simulator or devices, since it can't draw a half-pixel, and Autolayout doesn't align views on half-pixels.
For a layout like the one above I'd be giving a fixed height to the buttons (or to one button, and making the others equal it) and letting the black view take up the remaining space. It's always best to have at least one (ideally, exactly one) variable element in a full-screen layout basically to cover rounding errors.
It sounds at the moment like you have one fixed element (the black view) and the buttons are basically "take the remaining height and divide it between yourselves", which will only work if the remaining height divides perfectly.
I tried to set horizontal/vertical spaces between views equal to 0.5. The color of parent view acts as border color. It looks ugly in IB, it cannot layout views properly but resulting layout on device looks perfect.
In interface builder:
On simulator:
Constraints are a bit tricky. For each row:
set height for the 1st button
set equal height for all buttons
set equal width for all buttons (a bit different for rows with orange buttons)
align top edges of all buttons
align bottom edges of all buttons
set leading and trailing spaces between all buttons (including spaces to superview) to 0.5
set top space (to previous row) of 1st button to 0.5
You can apply constraints to multiple items at once. In order to apply leading/trailing spaces between buttons, place them without intersection in desired order before applying.

Resize superview and all superview's siblings using autolayout

I am trying to manage the views on my screen so that all views are updated in accordance with a text view that is growing depending on the text that is entered.
On my controller's view i have two subviews. Let's call them view1 and view2. View1 has a uitextview subview that is growing and shrinking depending on the text that is entered.
The issue I'm having is that view1 and view2 don't to grow and shrink whilst typing. The constraint constant for vertical spacing from the bottom on the textView has been set to 10px from it's superview. Vertical spacing between view1 and view2 is set to 0. Here is a visual representation of the view:
---------------------
| |
| ----------------- |
| | UITextView | |
| ----------------- |
| view1 |
---------------------
| |
| |
| |
| |
| view2 |
| |
| |
| |
| |
| |
---------------------
The result I'm getting whilst I add text to the textView is:
---------------------
| |
| ----------------- |
| | UITextView | |
| | | |
| | | |
---------------------
| |
| |
| |
| |
| view2 |
| |
| |
| |
| |
| |
---------------------
But the desired behavior would be something along the lines of:
---------------------
| |
| ----------------- |
| | UITextView | |
| | | |
| | | |
| | | |
| | | |
| | | |
| ----------------- |
| view1 |
---------------------
| |
| |
| view2 |
| |
| |
| |
---------------------
The strange thing is, once I've added the text and pressed submit (not added to diagram for simplicity), view1 grows to the correct size, as does view2, but not whilst typing.
Do I need to explicitly call setNeedsUpdateConstraints or updateConstraintsIfNeeded? If so, where? I have tried calling it from the text view delegate textViewDidChange: but nothing has helped.
Any help would be much appreciated.
I managed to figure this out.
For anyone reading this having the same issue, the way I did it was to write my own subclass of UITextView giving it a height constraint and a few delegate methods.
When changing the height of the text view, simply fire the delegate method (e.g. textViewDidChangeHeight:). Then, in the delegate call back implementation, I just called sizeToFit on the view.

iOS AutoLayout Ambiguous Layout in NavigationViewController

I have a navigation view controller, this view has only main view and when I trace auto layout I see this:
*<UIWindow:0x8a9de40> - AMBIGUOUS LAYOUT
| *<UILayoutContainerView:0x8bb7a50>
| | *<UINavigationTransitionView:0x8bbbfd0>
| | | *<UIViewControllerWrapperView:0x8bc55c0>
| | | | *<UIView:0x8bc4670>
| | | | | *<_UILayoutGuide:0x8bc46d0> - AMBIGUOUS LAYOUT
| | | | | *<_UILayoutGuide:0x8bc4990> - AMBIGUOUS LAYOUT
| | <UINavigationBar:0x8a94480>
| | | <_UINavigationBarBackground:0x8a9c790>
| | | | <_UIBackdropView:0x8bb82c0>
| | | | | <_UIBackdropEffectView:0x8bb7b60>
| | | | | <UIView:0x8bba5d0>
| | | | <UIImageView:0x8a9ca90>
| | | <UINavigationItemView:0x8a98370>
| | | | <UILabel:0x8a987e0>
| | | <_UINavigationBarBackIndicatorView:0x8bc1d00>
Does somebody know why UILayoutGuide is ambiguous?
The layout is ambiguous because of timing. If you run the trace after the view is visible, the ambiguity is resolved. https://stackoverflow.com/a/19129807/568295
The underlying "why" is an implementation detail. I would guess they are returning UIViewNoIntrinsicMetric for the intrinsicContentSize for the placeholder views for the top and bottom layout guides until after the navigation bar is displayed.

Resources