Easy-to-use HStack that snaps to elements on scroll.

Overview

SnapToScroll

Drop-in SwiftUI-based container view for horizontal snapping.

example-video.mp4

Getting Started

Using SnapToScroll is straightforward. There's just three steps.

  1. Import SnapToScroll
  2. Replace HStack with HStackSnap
  3. Add .snapAlignmentHelper to your view.

An example:

import SnapToScroll                               // Step 1
...

HStackSnap(alignment: .center(32)) {              // Step 2

    ForEach(myModels) { viewModel in

        MyView(
            selectedIndex: $selectedIndex,
            viewModel: viewModel
         )
         .snapAlignmentHelper(id: viewModel.id)   // Step 3
     }
}                  

For more examples, see SnapToScrollDemo/ContentView.swift.

Configuration

HStackSnap comes with two customizable properties:

  • alignment: The way you'd like your elements to be arranged.
    • leading(CGFloat): Aligns your child views to the leading edge of HStackSnap. This configuration supports elements of various sizes, so long as they don't take up all available horizontal space (which would extend beyond the screen). Use the value to set the size of the left offset.
    • center(CGFloat): Automatically aligns your child view to the center of the screen, using the offset value you've provided. This is accomplished with inside of the .snapAlignmentHelper which sets the frame width based on the available space. Note that setting your own width elsewhere may produce unexpected layouts.
  • coordinateSpace: Option to set custom name for the coordinate space, in the case you're using multiple HStackSnaps of various sizes. If you use this, set the same value in .snapAlignmentHelper.

.snapAlignmentHelper comes with two options as well:

  • id: Required. A unique ID for the element.
  • coordinateSpace: Same as above.

Limitations

  • HStackSnap is currently designed to work with static content.

How it Works

At render, HStackSnap reads the frame data of each child element and calculates the scrollOffset each element should use. Then, on DragGesture.onEnded, the nearest snap location is calculated, and the scroll offset is set to this point.

Read through HStackSnap.swift and Views/HStackSnapCore.swift for more details.

Credits

Thanks to pixeltrue for the illustrations used in example 2.

Comments
  • HStack alignment

    HStack alignment

    Is there a way to align all the items to the top. Normally HStack alignment is used to align the items inside to the desired position. For HStackSnap it is used for where it should snap.

    I'm trying to recreate what you have in example 2 but with 3 items above each other. My search result doesn't always give me a multiple of 3 since sometimes there are only 8 results. when this happens the last 2 are aligned in the middle

    opened by andredewaard 2
  • stuck in the center issue

    stuck in the center issue

    Hi there,

    I found an issue, if you scroll it fast in the beginning, it will stuck in the center sometimes.

    I know this is because of ScrollView. When you trigger the ScrollView's scrolling, the Views which are inside the ScrollView, cannot get the DragGesture anymore. But before that, they have already started part of the scrolling, so they cannot finish it. If you use other Containers, like LIst (it also has a similar vertical scrolling behavior), there's no problem like this. Do you have any idea about this?

    You could have a look at the effect here. https://jmp.sh/SdccqRX

    Thanks.

    opened by cuihonglei 1
  • Slider in View causes HStack to move also

    Slider in View causes HStack to move also

    I have a Slider in the View and when I move the slider, the View in the HStack also moves in the direction that I have moved the slider. Is there anyway to disable the gesture action in this lib while the Slider is moving?

    Let me know if any more information is required

    opened by Pau1fitz 0
  • It is not working on orientation change.

    It is not working on orientation change.

    If you change orientation to landscape, HStackSnap not working as expected. I think there is a problem because the width of the stack is changed. Is there any solution for this?

    HStackSnap(alignment: .leading(20)) {
      ForEachWithIndex(elements: self.dayStore.days) { index, day in
          GeometryReader { cardGeo in
              VStack {
                  Text("cao \(index)")
              }
              .frame(maxWidth: .infinity)
              .frame(maxHeight: .infinity)
              .background(RoundedCorners(color: Color("Neutral White"), tl: 20, tr: 20, bl: 20, br: 20))
              .rotation3DEffect(Angle(degrees: (Double(cardGeo.frame(in: .global).minX))) / -30, axis: (x: 0, y: 10.0, z: 0))
              .snapAlignmentHelper(id: day.id)
          }
          .frame(width: abs(geo.size.width - 80))
          .frame(maxHeight: .infinity)
      }
    }
    .padding(.top, 10)
    .padding(.bottom, 10)
    
    opened by MrEldin 2
  • Does not work when nested in a `NavigationView`

    Does not work when nested in a `NavigationView`

    Hello! I'm noticing an issue where the library doesn't work when nested in a NavigationView. The views are displayed correctly, however I am unable to scroll only when nested in a NavigationView. I have included a very simple implementation reusing your demo to show what is happening. card test.zip

    opened by shawna-mac 1
Releases(1.0.2)
Owner
null
Easily use UIKit views in your SwiftUI applications. Create Xcode Previews for UIView elements

SwiftUIKitView Easily use UIKit views in SwiftUI. Convert UIView to SwiftUI View Create Xcode Previews from UIView elements SwiftUI functional updatin

Antoine van der Lee 682 Dec 29, 2022
Oovium's AetherView and other basic UI elements necessary for embedding Oovium in other apps

Oovium's AetherView and other basic UI elements necessary for embedding Oovium in other apps

Joe Charlier 0 Aug 24, 2022
A horizontal scroll dial like Instagram.

HorizontalDial Preview Requirements iOS 8.0+ Swift 5 Storyboard support Installation CocoaPods use_frameworks! pod "HorizontalDial" Manually To instal

Lee Sun-Hyoup 210 Nov 22, 2022
Medium's upper and lower Menu in Scroll.

Notice: MediumScrollFullScreen is no longer being maintained/updated. MediumScrollFullScreen Medium's upper and lower menu in Scroll. Demo Description

Hiroki Nagasawa 548 Nov 17, 2022
A paging scroll view for SwiftUI, using internal SwiftUI components

PagingView A paging scroll view for SwiftUI, using internal SwiftUI components. This is basically the same as TabView in the paging mode with the inde

Eric Lewis 18 Dec 25, 2022
Paging Library for Infinity Scroll using RxSwift

Paging Library for Infinity Scroll using RxSwift

SubinJang 2 Mar 31, 2022
An easy to use FAQ view for iOS written in Swift

FAQView An easy to use FAQ view for iOS written in Swift. This view is a subclass of UIView. Setup with CocoaPods If you are using CocoaPods add this

Mukesh Thawani 467 Dec 5, 2022
Powerful and easy-to-use vector graphics Swift library with SVG support

Macaw Powerful and easy-to-use vector graphics Swift library with SVG support We are a development agency building phenomenal apps. What is Macaw? Mac

Exyte 5.9k Jan 1, 2023
An easy to use UI component to help display a signal bar with an added customizable fill animation

TZSignalStrengthView for iOS Introduction TZSignalStrengthView is an easy to use UI component to help display a signal bar with an added customizable

TrianglZ LLC 22 May 14, 2022
An easy to use FAQ view for iOS written in Swift

FAQView An easy to use FAQ view for iOS written in Swift. This view is a subclass of UIView. Setup with CocoaPods If you are using CocoaPods add this

Mukesh Thawani 466 Nov 9, 2021
Easy to use, highly customizable gauge view

GDGauge - Customizable Gauge View Requirements Xcode 11+ Swift 5 iOS 9+ Installation Swift Package Manager .package(url: "https://github.com/saeid/GDG

Saeid 74 Dec 5, 2022
Use the iPhone X notch in creative ways 👩‍🎨👨‍🎨.

NotchToolkit NotchToolkit is a framework for iOS that allow developers use the iPhone X notch space in creative ways. Inspired by I was working on thi

Ahmed Bekhit 56 Nov 22, 2022
A child view controller framework that makes setting up your parent controllers as easy as pie.

Description Family is a child view controller framework that makes setting up your parent controllers as easy as pie. With a simple yet powerful publi

Christoffer Winterkvist 246 Dec 28, 2022
Kit for building custom gauges + easy reproducible Apple's style ring gauges.

GaugeKit ##Kit for building custom gauges + easy reproducible Apple's style ring gauges. -> Example Usage Open GaugeKit.xcworkspace and change the sch

Petr Korolev 1k Dec 23, 2022
An easy way to add a shimmering effect to any view with just one line of code. It is useful as an unobtrusive loading indicator.

LoadingShimmer An easy way to add a shimmering effect to any view with just single line of code. It is useful as an unobtrusive loading indicator. Thi

Jogendra 1.4k Jan 4, 2023
An iOS Library that makes shadows management easy on UIView.

ShadowView is an iOS Shadow library that makes view's shadow implementation easy and sweet ?? ?? . Add simple shadows to add a gaussian blurred projec

Pierre 404 Dec 8, 2022
Twinkle is a Swift and easy way to make any UIView in your iOS or tvOS app twinkle.

Twinkle ✨ Twinkle is a Swift and easy way to make any UIView in your iOS or tvOS app twinkle. This library creates several CAEmitterLayers and animate

patrick piemonte 600 Nov 24, 2022
UIPheonix is a super easy, flexible, dynamic and highly scalable UI framework + concept for building reusable component/control-driven apps for macOS, iOS and tvOS

UIPheonix is a super easy, flexible, dynamic and highly scalable UI framework + concept for building reusable component/control-driven apps for macOS, iOS and tvOS

Mohsan Khan 29 Sep 9, 2022
Windless makes it easy to implement invisible layout loading view.

Windless Windless makes it easy to implement invisible layout loading view. Contents Requirements Installation Usage Looks Credits Communication Licen

ArLupin 940 Dec 22, 2022