Git Product home page Git Product logo

tllayouttransitioning's Introduction

TLLayoutTransitioning

Enhanced transitioning between UICollectionView layouts in iOS.

##Overview

TLLayoutTransitioning provides a TLLayoutTransition transition layout subclass and a UICollectionView+TLTransitioning category that combine to solve a few problems with collection view layout transitioning:

  1. UICollectionViewLayoutTransition does not handle content offset well, often leaving cells where you don't want them. TLTransitionLayout provides elegant control of content offset with Minimal, Visible, Center, Top, Left, Bottom or Right placement options relative to one or more index paths.

  2. UICollectionViewLayoutTransition does not support supplementary views. TLTransitionLayout provides support for any supplementary view kinds specified in the initializer.

  3. -[UICollectionView setCollectionViewLayout:animated:completion] has serious known bugs in iOS7 and does not provide any animation options. TLLayoutTransitioning provides a robust alternative to this API with support for animation duration, 30+ easing curves and content offset control. This is done by using CADisplayLink to drive an interactive TLTransitionLayout as a non-interactive animation. Note that this approach may not perform as well as Core Animation with more complex cells.

Check out the demos in the Examples workspace!

###TLTransitionLayout Class

TLTransitionLayout is a subclass of UICollectionViewTransitionLayout that interpolates linearly between layouts and optionally between the current content offset and a specified final offset.

The final offset is specified by setting the toContentOffset property. The UICollectionView+TLTransitioning category provides an API for calculating Minimal, Visible, Center, Top, Left, Bottom or Right offset placements relative to one or more index paths.

The basic usage is as follows:

- (void)someViewControllerEventHandler
{
    UICollectionViewLayout *nextLayout = ...;
    self.transitionLayout = (TLTransitionLayout *)[self.collectionView startInteractiveTransitionToCollectionViewLayout:nextLayout 
                                        completion:^(BOOL completed, BOOL finish) {
	    if (finish) {
            self.collectionView.contentOffset = self.transitionLayout.toContentOffset;
            self.transitionLayout = nil;
	    }
    }];
    NSArray *indexPaths = ...;// some selection of index paths to place
    self.transitionLayout.toContentOffset = [self.collectionView toContentOffsetForLayout:self.transitionLayout indexPaths:indexPaths placement:TLTransitionLayoutIndexPathPlacementCenter];
}

- (UICollectionViewTransitionLayout *)collectionView:(UICollectionView *)collectionView transitionLayoutForOldLayout:(UICollectionViewLayout *)fromLayout newLayout:(UICollectionViewLayout *)toLayout
{
    NSArray *supplementaryKinds = ...; // optional supplementary view kinds
    return [[TLTransitionLayout alloc] initWithCurrentLayout:fromLayout nextLayout:toLayout supplementaryKinds:supplementaryKinds];
}

Note that the collection view will reset contentOffset after the transition is finalized, but as illustrated above, this can be negated by setting it back to toContentOffset in the completion block.

####Canceling a Transition

If you want to stop the current transition to start a new one from the current position, you need a way to stop the current transition in-place. Apple provides finishInteractiveTransition and cancelInteractiveTransition to end a transition, but neither of these stops the transition in-place. So, TLLayoutTransitioning provides such a method:

[self.collectionView cancelInteractiveTransitionInPlaceWithCompletion:^(){
    // initiate new transition in the completion block
}];

You can find out if a transition is currently in progress by checking the isInteractiveTransitionInProgress on UICollectionView.

###UICollectionView+TLTransitioning Category

The UICollectionView+TLTransitioning category provides some of useful methods for calculating for interactive transitions. In particular, the toContentOffsetForLayout:indexPaths:placement API calculates final content offset values to achieve Minimal, Visible, Center, Top, Left, Bottom or Right placements for one or more index paths. The expanded version of this API provides for even further fine-tuning and supports transitioning to a different collection view size and content inset:

- (CGPoint)toContentOffsetForLayout:(UICollectionViewTransitionLayout *)layout
                         indexPaths:(NSArray *)indexPaths
                          placement:(TLTransitionLayoutIndexPathPlacement)placement
                    placementAnchor:(CGPoint)placementAnchor
                     placementInset:(UIEdgeInsets)placementInset
                             toSize:(CGSize)toSize
                     toContentInset:(UIEdgeInsets)toContentInset

UICollectionView+TLTransitioning also provides an alternative to -[UICollectionView setCollectionViewLayout:animated:completion] for non-interactive animation between layouts with support for animation duration, 30 built-in easing curves (courtesy of Warren Moore's AHEasing library), user defined easing curves (by defining custom AHEasingFunctions) and content offset control. The basic transition call is as follows:

TLTransitionLayout *layout = (TLTransitionLayout *)[collectionView transitionToCollectionViewLayout:toLayout duration:2 easing:QuarticEaseInOut completion:nil];
CGPoint toOffset = [collectionView toContentOffsetForLayout:layout indexPaths:@[indexPath] placement:TLTransitionLayoutIndexPathPlacementCenter];
layout.toContentOffset = toOffset;

where the view controller is configured to provide an instance of TLTransitionLayout as described above. Check out the Resize sample project in the Examples workspace to see this in action.

##Installation

###CocoaPods

Add the following to your Podfile

pod 'TLLayoutTransitioning'

###Carthage

Add the following to your Cartfile

github "wtmoose/TLLayoutTransitioning"

Note that TLLayoutTransitioning has a dependency on AHEasing, which does not support Carthage. As a workaround, TLLayoutTransitioning's Cartfile uses the wtmoose/AHEasing fork which adds Carthage support.

To request Carthage support for the canonical AHEasing library, consider leaving a comment in favor of reopening the Add dynamic frameworks support pull request.

###Manual

If you're not using a dependency manager, check out the noframeworks branch and copy the following files into your project:

TLTransitionLayout.h
TLTransitionLayout.m
UICollectionView+TLTransitionAnimator.h    
UICollectionView+TLTransitionAnimator.m

And copy the following files from AHEasing:

easing.h
easing.c

##Examples

Open the Examples workspace (not the project) to run the sample app. The following examples are included:

###Resize

The Resize example combines TLTransitionLayout and -[UICollectionView+TLTransitioning transitionToCollectionViewLayout:duration:easing:completion:] as a better alternative to -[UICollectionView setCollectionViewLayout:animated:completion]. Experiment with different durations, easing curves and content offset options on the settings panel. Toggle "show section headers" to see transitioning supplementary views.

###Pinch

The Pinch example demonstrates a simple pinch-driven interactive transition using TLTransitionLayout. The destination contentOffset is selected such that the initial visible cells remain centered. Or if a cell is tapped, the contentOffset the cell is centered.

About SwiftKick Mobile

We build high quality apps! Get in touch if you need help with a project.

tllayouttransitioning's People

Contributors

adriantofan avatar dillan avatar falconser avatar readmecritic avatar wtmoose avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tllayouttransitioning's Issues

Cancel transition

Hello again,

I have a situation where if i rotate my device while performing a layout transition the app errors with the following error:

the collection is already in the middle of an interactive transition

So I was wondering if there was a way I could cancel the transition if one was in progress?

Exception during pinch gesture handling.

When testing pinch gestures in rapid succession (aka toddler testing) I see the following exception raised.

2015-08-05 17:44:06.512 Examples[904:731529] *** Assertion failure in -[UICollectionView _finishInteractiveTransitionShouldFinish:finalAnimation:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3491.2.5/UICollectionView.m:2981
2015-08-05 17:44:20.445 Examples[904:731529] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the collection was not prepared for an interactive transition. see startInteractiveTransitionToCollectionViewLayout:completion:'

I believe this reopens #17.

I encountered this on iOS 9 (13A4305g), but suspect that the issue can present itself on other versions as well.

Here is what I think might be going on:

  1. Disabling the pinch gesture recognizer in the pinch handling method is causing the handling code to be called twice so [self.collectionView finishInteractiveTransition] or [self.collectionView cancelInteractiveTransition] could get called while the transition to completion is already in flight.
  2. The logic in the pinch handling code is falling through to the final else clause in more situations than are likely intended. For example, if the pinch gesture state is UIGestureRecognizerStateChanged and self.transitionLayout == nil or pinch.numberOfTouches <= 1.

catch a error what it means?

*** Assertion failure in -[NSISLinearExpression incrementConstant:], /SourceCache/Foundation/Foundation-1047.25/Layout.subproj/IncrementalSimplex/NSISLinearExpression.m:620

indexPath on Resize demo

Hi, Love your work mate.

The Resize example is giving an error on line 68 of the CollectionViewController when trying to set the property of 'keyIndexPath' which does not exist in the TLTrans header.

Does it simply need to be added?

Cheers!

Transition crashes when the number of sections in the datasource increases

Hey Tim, thanks for creating this. It was working well for me when I had only one section in my collection view, but now with multiple sections I'm experiencing a crash during transitionToCollectionViewLayout:duration:easing:completion: that I wasn't experiencing with the stock setCollectionViewLayout:animated:completion: method.

The setup:
I have a collection view that supports a transition between a 1-wide grid layout and a 4-wide grid layout. The cells in the collection view are sectioned by month (Sept 2014, August 2014, ...) and the content is paginated such that when the user scrolls to the bottom new content is requested from my API and appended to my dataSource (currently just calling reloadData instead of performing any insertion updates).

Steps:

  1. Start with a 1-wide grid. Transition to a 4-wide grid. Technically there's still only 1 section at this point, because we're still in the first month of data.
  2. Scroll down a few pages in the 4-wide grid until we've reached the next section.
  3. Attempt to transition back to the 1-wide grid results in a crash at this line:
UICollectionViewLayoutAttributes *toPose = reverse
                    ? [self.currentLayout layoutAttributesForItemAtIndexPath:indexPath]
                    : [self.nextLayout layoutAttributesForItemAtIndexPath:indexPath];

Because self.nextLayout's layoutAttributesForItemAtIndexPath:indexPath returns nil when the section index > 0. The error is:

Uncaught exception: *** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]

It appears that when I transition from the 1-wide layout, there's only one section in existence. Then, after scrolling the 4-wide layout, there's multiple sections. Attempting to go back to the 1-wide layout, the crash occurs.

If I scroll through many sections while in the 1-wide layout, and then scroll back up, I'm free to transition between layouts since the number of sections in the 1-wide layout is in sync with the number of sections in the 4-wide layout.

Any idea how to fix this? I'd very much like to continue using your library.

Thanks!

Examples not building

Many errors like Pods-TLIndexPathTools-prefix.pch:2:9: Could not build module 'UIKit' or CoreFoundation.h:11:10: Could not build module 'Darwin' occur when trying to run the Examples project for iOS 7.1 simulator in Xcode 5.1 (5B130a) straight from the repo, no modifications.

Resize example crashes when double clicking a cell

Tim, thank you very much for building this. I'm playing around the resize example. When double clicking a cell, the program crashes. The error message is: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the collection is already in the middle of an interactive transition'. I guess the beginIgnoringInteractionEvents and endIgnoringInteractionEvents calls should be added in collectionView:didSelectItemAtIndexPath:?

Resize / scale question

I'm playing around with the transition of the CollectionViewLayout of the examples (pinch or resize) and couldn't figure out how to autoresize the content of the cell between the small and large layout.

E.g. I have an UILabel within the CollectionViewCell which should be half the width of the cell at a defined (fixed) position. When the transition to the large layout is finished, the label should be also half of the cell (same relative position), but with a larger font size (or resized).

Use autolayout here or scale the contentView with CGAffineTransformMakeScale?

Any advice would be helpful .. ;)

Podfile configuration for example

The TLLayoutTransitioning pod local path should be '../' insead of '..'

pod 'TLLayoutTransitioning', :path => '../'

Otherwise it gives me the following error

Fetching podspec for TLLayoutTransitioning from ..
[!] Unable to satisfy the following requirements:

  • TLLayoutTransitioning (from..) required by Podfile

Jarring snap at end of interactive transition.

I've noticed a jarring snap to an unintended position when the user lifts their fingers, ending the pinch gesture. After the layout snaps to the unintended position it will animate back to the expected layout.

interactive_transition_snap

Public Headers

When building the framework, the following headers aren't Public, Private or Project.

  • TLTransitionLayout.h
  • UICollectionView+TLTransitioning.h

This renders the .framework useless at the moment when built via Carthage (but I suppose that'd be the case for anything else as well)

Could you please include those headers in the framework as well. I've tried this locally but forgot to fork it and send a PR. If you'd like, I could do that tomorrow.

Getting crash in pinch gesture after pagination

Hi ,

I'm getting crash when I try to use pics gesture after loading data using pagination. Initially it's working fine but when load data using pagination and try to using animation application get crashed. Below are the error message which I'm getting from Xcode
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Rounding frame ({{-8.9884656743115785e+307, -8.9884656743115785e+307}, {1.7976931348623157e+308, 1.7976931348623157e+308}}) from preferred layout attributes resulted in a frame with one or more invalid members ({{-inf, -inf}, {inf, inf}}). Layout attributes: <UICollectionViewLayoutAttributes: 0x1505aa6a0; index path: (30-0); frame = (-8.98847e+307 -8.98847e+307; 1.79769e+308 1.79769e+308); non-affine transform; alpha = -0.00456592> View: <GalleryApp.SelectPhotoCell: 0x150910920; baseClass = UICollectionViewCell; frame = (-8.98847e+307 -8.98847e+307; 1.79769e+308 1.79769e+308); transform3D = [-0.00456592, 0, 0, 0; 0, -0.00456592, 0, 0; 0, 0, -0.00456592, 0; 0, 0, 0, -0.00456592]; clipsToBounds = YES; alpha = -0.00456592; hidden = YES; opaque = NO; layer = <CALayer: 0x282e18f00>>'

Please let me know if we have any solution.

Hi Tim - I get this error on demo

the demo can't find TLCollectionViewController.

TLCollectionViewController', superclass of 'CollectionViewController'; did you mean 'UICollectionViewController'?

did this file get misplaced from repo?

Cheers
JP

layout transition for supplementary views

Hi Tim,

I'm currently making use of your TLLayoutTransitioning class and it is really easy to use! Thanks a lot for developing this! Actually, I encountered a problem with transition with supplementary views. In my project, instead of only one section, I have two sections in the collection view, and for each section, there is a header view and a footer view. However, after applying your resizing example, the header view and footer view are gone after doing a layout transition (animate cells to be bigger.) I don't think this is an issue with your implementation, but I just have no idea how to accommodate supplementary views in your example (Maybe there is a way to fix it easily which I'm not aware of.).
So, if at all possible, could you also add some header view/footer view in your resizing example so that I can study from it? I'm in desperate need of a way to make my project work...

Thanks a lot in advance!

Sincerely,

Frank

Memory leak

Hello, I am using your collectionview transition in my app and I appear to have a memory leak and xcodes profiler indicates it is here:

UICollectionViewTransitionLayout *transitionLayout = [self startInteractiveTransitionToCollectionViewLayout:layout completion:^(BOOL completed, BOOL finish) {
UICollectionViewTransitionLayout *transitionLayout = [self tl_transitionLayout];
if ([transitionLayout conformsToProtocol:@protocol(TLTransitionAnimatorLayout)]) {
idlayout = (id)transitionLayout;
[layout collectionViewDidCompleteTransitioning:self completed:completed finish:finish];
}
[self tl_setAnimationDuration:nil];
[self tl_setAnimationStartTime:nil];
[self tl_setTransitionLayout:nil];
[self tl_setEasingFunction:NULL];
if (completion) {
completion(completed, finish);
}
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}];

I am unsure of how to fix this, can you help?

No source files in framework target.

The framework target needs to include the .m files.

Also, AHEasing needs to be added to Linked Frameworks and Libraries.

These changes are needed for the framework to be used with Carthage.

pinch again during animation

Hello guys,

First of all thank you for this awesome library !

I have a crash in my app made after your pinch example. Basically if I pinch and let, there is a animation that continues until it stabilizes. If I pinch again during this animation I get an exception

2015-05-07 17:46:49.804 Tradee[4684:1227320] *** Assertion failure in -[UICollectionView _finishInteractiveTransitionShouldFinish:finalAnimation:], /SourceCache/UIKit/UIKit-3347.44/UICollectionView.m:2897
2015-05-07 17:47:03.124 Tradee[4684:1227320] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the collection was not prepared for an interactive transition. see startInteractiveTransitionToCollectionViewLayout:completion:'

Any ideas on how to fix this ? Or maybe point me in the right direction ?

Thank you,
Adrian

Disable bounce effect in interactive transitions

Hi!

There seems to be a bounce effect when you complete an interactive transition, I'd like to replace that by just decelerating to final position without bouncing.

You can check this effect in the Example project, if you pinch and release it'll complete the interactive transition with a bounce effect going a bit further than final progress in some cases.

The workaround I found is to subclass TLTransitionLayout and override the setProgress:time: method limiting values to 0..1

- (void)setTransitionProgress:(CGFloat)transitionProgress time:(CGFloat)time
{
    [super setTransitionProgress:MAX(0, MIN(transitionProgress, 1.f)) time:MAX(0, MIN(time, 1.f))];
}

This does get rid for the bounce effect (it's no longer visible to the user) but the transition still takes some time to complete because it thinks it's bouncing.

Any idea how can I solve this issue?

Thanks in advance,

Nicolás.

UICollectionView not centering transition in iOS 9, worked fine in iOS 8.

The app essentially transitions between two different UICollectionViewFlowLayouts in a UICollectionView. I've not had a single problem with the TLLayoutTransitioning class prior to iOS 9. Thanks so much for taking the time to make and share this, by the way! It's a life saver. :)

For some reason since updating to iOS 9 (app still compiled for 8+) the transition doesn't center the offset, and instead seems to throw the whole transition off now while transitioning from large to small layouts, as seen here:

ripewellwornkagu-size_restricted

Any thoughts what might've changed?

-[UICollectionViewTransitionLayout setToContentOffset:]: unrecognized selector

This library is super helpful! Thank you so much! But I'm getting this bug suddenly:

"[UICollectionViewTransitionLayout setToContentOffset:]: unrecognized selector sent to instance 0x146f8360"

Specifically my stack trace breaks at the following line in your example:

"layout.toContentOffset = toOffset;"

If I comment it out, everything works fine, except, obviously, I no longer get that awesome offset during transitions. The problem, as best as I can tell, is that the following line of code is returning a [UICollectionViewTransitionLayout] and therefore isn't being properly typed to your [TLTransitionLayout] subclass for some reason:

"TLTransitionLayout *layout = (TLTransitionLayout *)[collectionView transitionToCollectionViewLayout:toLayout duration:2 easing:QuarticEaseInOut completion:nil];"

When I NSLog the 'layout' object, it's definitely a [UICollectionViewTransitionLayout] type, not [TLTransitionLayout]. And, obviously, the [UICollectionViewTransitionLayout] class doesn't have the property "toOffset" I need, hence the error I'm experiencing. I've searched all over since this problem popped up over 9 hours ago, and zero solutions have helped. I've ensured all headers are included with #import and the implementation files are all being compiled within the correct target. I've cleared all my Derived Data, etc. Even uninstalled and reinstalled Xcode. I'm certainly lost. It just stopped working suddenly. I know it must be PEBKAC, but I can't for the life of me figure out how that can be. :( Anyhow, thanks a bunch for any insight. It was spectacular when it was working for me. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.