KelvinJin / AnimatedCollectionViewLayout

A UICollectionViewLayout subclass that adds custom transitions/animations to the UICollectionView without effecting your existing code.
MIT License
4.73k stars 349 forks source link

Library Usage #8

Open heuism opened 7 years ago

heuism commented 7 years ago

problem

after i followed the thing, i got this as result.

It doesnt seem like it working right. Just a normal CollectionView and even the snap is not on point. Can you help me with this? I am newbie.

the following code

super.viewDidLoad()

        animator = (ParallaxAttributesAnimator(), true)
        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Register cell classes
//        self.collectionView!.register(SimpleCollectionViewCell.self, forCellWithReuseIdentifier: "CollectionCell")
//        
//        self.collectionView?.register(<#T##cellClass: AnyClass?##AnyClass?#>, forCellWithReuseIdentifier: <#T##String#>)

        // Do any additional setup after loading the view, typically from a nib.

        // Must turn paging on.
        collectionView?.isPagingEnabled = true

        if let layout = collectionView?.collectionViewLayout as? AnimatedCollectionViewLayout {
            layout.animator = animator?.0
        }
KelvinJin commented 7 years ago

Hey @heuism, I think there're several possible reasons.

heuism commented 7 years ago

i copied everything in your iOS example code.

But when i actually do the extension as yours instead of put everything inside of the normal controller the code works fine. @@ i AM not too sure :)). Can you explain to me in your own idea?

Btw,

let layout = AnimatedCollectionViewLayout()
layout.animator = animator?.0
layout.scrollDirection = .horizontal
collectionView!.collectionViewLayout = layout
        if let layout = collectionView?.collectionViewLayout as? AnimatedCollectionViewLayout {
            print("Is there a layout?")
            layout.animator = animator?.0
        }

When i did the code below the code doesn't go insdie the if let closure. And when i do the normal way as you show on the manual i have to put another layout.scrolldirection = .horizontal in order to make it work in horizontal. Besides all of these problems, i make it works already.

Thanks a lot @KelvinJin

heuism commented 7 years ago

I got a question about screen rotation, how can i do to keep the animation the same for both rotation? cause at the moment it seems screwed up when i try to rotate it.

Thanks @KelvinJin

KelvinJin commented 7 years ago
 if let layout = collectionView?.collectionViewLayout as? AnimatedCollectionViewLayout {
            print("Is there a layout?")
            layout.animator = animator?.0
        }

This won't work in your case. It works in my case because I set it up in Storyboard (sorry for that, I didn't mention how you can do that in the README). You need to do the normal way. Yeah, vertical is not supported yet, only horizontal. I'm currently working on it. So stay tuned!

I haven't tested on screen rotation yet. I can see there might be issues. I'll investigating a bit more later on once i finish vertical support.

heuism commented 7 years ago

Thanks @KelvinJin, yeah i have been trying to test around, play around with that to see the screen rotation effect.

But yeah, i will keep updating to see if this thing can be successful

nataliachodelski commented 7 years ago

@heuism, I figured out how to fix this issue. I encountered it too when using this library with the RotateInOutAttributesAnimator. I hope this will be helpful for your issue. It totally fixed the issue in my project.

@KelvinJin, i would be happy to add this into the library. Can you point me to where i should include this logic and i'll make a pull request?

So my fix for this situation where the cards don't fill the frame properly after the animation but remain offset from the collectionView frame: Have your UICollectionViewController impliment the UIScrollViewDelegate protocol, then add the delegate method func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>).

This method calculates the current cell based on size of the cell and the content offset of the collection view and then works out how to adjusts the center point so the cell will fit properly into the desired frame, and passes this adjustment to the CollectionView using the targetContentOffset's property, with is basically an inout pointer. Source: http://stackoverflow.com/a/35436300/.

    // snaps cell back into desired position after scrolling
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
                //Ensure the scrollview is in the collectionView we care about
        if (scrollView == self.myCollectionView) {

            // Find cell closest to the frame centre with reference from the targetContentOffset.
            let frameCenter: CGPoint = self.collectionView.center
            var targetOffsetToCenter: CGPoint = CGPoint(x: targetContentOffset.pointee.x + frameCenter.x, y: targetContentOffset.pointee.y + frameCenter.y)
            var indexPath: IndexPath? = self.myCollectionView.indexPathForItem(at: targetOffsetToCenter)

            // Check for "edgecase" that the target will land between cells and then find a close neighbor to prevent scrolling to index {0,0}.
            while indexPath == nil {
                targetOffsetToCenter.x += 10
                indexPath = self.myCollectionView.indexPathForItem(at: targetOffsetToCenter)
            }
            if let index = indexPath {
                // Find the centre of the target cell
                if let centerCellPoint: CGPoint = myCollectionView.layoutAttributesForItem(at: index)?.center {

                    // Calculate the desired scrollview offset with reference to desired target cell centre.
                    let desiredOffset: CGPoint = CGPoint(x: centerCellPoint.x - frameCenter.x, y: centerCellPoint.y - frameCenter.y)
                    targetContentOffset.pointee = desiredOffset
                }
            }
        }
    }

For reference, i'm using this library with the RotateInOutAnimator in a horizontally paging UICollectionView. My setup of the animator in viewDidLoad:

        let layout = AnimatedCollectionViewLayout()
        layout.animator = RotateInOutAttributesAnimator(minAlpha: 0.6, maxRotate: 0.1)
        layout.scrollDirection = .horizontal

        layout.itemSize = CGSize(width: myCollectionView.bounds.size.width, height: myCollectionView.bounds.size.height)
        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        myCollectionView?.collectionViewLayout = layout

And I also added these CustomFlowLayout methods in my CollectionViewController, but these alone did not address the issue:

    // MARK: Collection View CustomFlowLayout setup / size / layout specifics
    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
        return CGSize(width: myCollectionView.bounds.size.width, height: myCollectionView.bounds.size.height )
    }

    // for custom flow animation
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return .zero
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
KelvinJin commented 7 years ago

@nchodelski Hey, thanks for sharing those. Ideally, the pagingEnabled property of UICollectionView will take care of the "Snap" behaviour, which can be seen in the sample app. I wonder if you have a minimum sample project that can show the issue you're having?

heuism commented 7 years ago

@nchodelski, thanks for this suggestion, i haven't got a chance to test that but thanks for your help. I will reply again when i got a chance to test that 👍.

athemer commented 7 years ago

Hi, does the collectionView size have to be full screen ? what if i want to pin my collectionView only at the 1/3 top of the view ? thanks