Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alignment horizontal scroll collection view #60

Open
palozinski opened this issue Mar 21, 2020 · 6 comments
Open

Alignment horizontal scroll collection view #60

palozinski opened this issue Mar 21, 2020 · 6 comments

Comments

@palozinski
Copy link

Hey,

any idea hot to align horizontal collection view items to left when it is first item then after that could work normally with centered item. Like AppStore product carousel ...

@MaherKSantina
Copy link
Owner

Hey @palozinski ! So sorry for the late reply 😢 I've been soo busy at work and life.
I was looking into the AppStore but couldn't find the behavior you've mentioned. Is it okay if you show me a video for the behavior?

@julianvogels
Copy link

julianvogels commented Jun 5, 2020

Hi Maher, thanks for this library. I'm going to hijack this issue because I think I'm looking for the same thing.
Our designer does not like the empty space on the left of the first element, and would like the first cell it to be left aligned, showing more of the second element. In the App Store and in your implementation, the first cell is center aligned. Once the user scrolls to the second cell, and any subsequent cell, the cell would centered with peeking cells left and right, but not the first one.

I was thinking about how to do this, and I think it's rather complicated? I guess you would need to make itemLength aware of whether or not it is the first item, and then return the length without doubling the offset. But you'd also have to adjust it's x position, the paging behavior and calculations.
Can you already see a way to implement this off the top of your head?

If my designer doesn't reconsider, I could then help implement it.

@MaherKSantina
Copy link
Owner

Hello @julianvogels ! I'm so sorry for the late reply...
Thank you for the detailed explanation! Yeah I can't think of the best way to implement this from the top of my head but yeah you're right we would need to check the position of the item and calculate the item length, scroll position and spacing based on that. It seems like a common business requirement that's going on so it looks like a good idea to add it in. However, I don't think I would be able to push it in these couple of weeks because I'm soooo swamped at work 😢 It would be amazing if you can come up with a solution and I'd really appreciate it. Now the good news is that the collection view layout and paging is all custom made, so I think the modifications on that would be easier than doing it on the UIKit default one. I think the only challenge is to migrate through the code and understand what's going on, I suck at writing comments on code so sorry about that 😢

@palozinski
Copy link
Author

Hey, @MaherKSantina here is an example from the AppStore. Please look at the first item it is always great aligned to left and you can see the next item. Then further items are really great center and you can see both left and right side items.
ezgif com-video-to-gif (1)

@MaherKSantina
Copy link
Owner

Hello @palozinski ! Thanks for the recording! So here's my explanation
Although it seems like there is no space on the left, there actually is, here's a screenshot from the gif you just shared:

Screen Shot 2020-06-13 at 12 36 27 PM

If you look closely you would see that there is some padding but since the peeking is small in width it doesn't show, here's another screenshot of the space with arrows showing that there is actually space on the left:

Screen Shot 2020-06-13 at 12 36 27 PM

The arrows on the left and right have the same width, and essentially you can fit a peeking cell on the left within that space and it will look exactly like the one on the right.

To validate that using this library you can run the demo project and set the peeking width to something small (Something between 10-15 points) and it should look something similar to the app store

Hope this helps, please let me know if you have any questions 🙏

@un0dvendig
Copy link

un0dvendig commented Aug 5, 2020

If anyone still needs a solution for showing first and last cells with custom paddings, I think I might have found a workaround.

Basically, all you need to do is to change contentInset property of the collection view, that is using MSCollectionViewPeekingBehavior.

Let's assume, that you have some constants CellSpacing and VisibleCellWidth, that are used for initializing MSCollectionViewPeekingBehavior object (or if you just change its properties).

Something like:

let collectionViewPeekingBehavior = MSCollectionViewPeekingBehavior(
        cellSpacing: CellSpacingValue
        cellPeekWidth: VisibleCellWidthValue
        minimumItemsToScroll: nil,
        maximumItemsToScroll: nil,
        numberOfItemsToShow: 1,
        scrollDirection: .horizontal,
        velocityThreshold: 0.2
    )

To calculate proper collection view's content insets, you have to calculate left and right insets separately (I have no idea why they are different, but I found out by trial and error that right content inset should differ from the left one by exactly one cell spacing). So it will look like this:

let leftInset = VisibleCellWidth + CellSpacing
let rightInset = VisibleCellWidth + CellSpacing + CellSpacing

And now the magic workaround part. You have to use calculated values but with opposite sign (i.e. negative values) as collection view content insets like this:

collectionView.contentInset = .init(
    top: 0,
    left: -leftInset,
    bottom: 0,
    right: -rightInset
)

This should remove left inset for the first cell and right inset for the last cell.

Note, that I tested this only for collection view with HORIZONTAL scroll direction, that shows 1 cell, but I think it should work for collection view with vertical scroll direction too, only that you should calculate top and bottom insets, obviously. Might even work for more cells in the screen.

Now, if you want to add insets and not just remove them, then you have to add preferred values to the NEGATIVE calculated values, and use new calculated value AS IT IS like this:

let leftInset = VisibleCellWidth + CellSpacing
let rightInset = VisibleCellWidth + CellSpacing + CellSpacing

let preferredLeftInset = -leftInset + PreferredValueForLeftInset
let preferredRightInset = -rightInset + PreferredValueForRightInset

collectionView.contentInset = .init(
    top: 0,
    left: preferredLeftInset,
    bottom: 0,
    right: preferredRightInset
)

Hope it helps to anyone.

And also @MaherKSantina thank you for your work on this library. Saved a lot of time by using it. 🔥

UPD: Added gifs showing workaround applied to the example project

             [zero insets]                  [15 left inset & 30 right inset]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants