Skip to content

Instantly share code, notes, and snippets.

@valvoline
Created March 26, 2021 11:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save valvoline/cd426ae3f82f7b5bfb0b28703c35507c to your computer and use it in GitHub Desktop.
Save valvoline/cd426ae3f82f7b5bfb0b28703c35507c to your computer and use it in GitHub Desktop.
A simple Parallax Effect based paged ScrollView
//
// ContentView.swift
// Shared
//
// Created by Costantino Pistagna on 25/03/21.
//
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader { geometry in
ScrollView(.horizontal) {
TabView {
SplashPageView(iconName: "paperplane.circle.fill",
title: "Welcome to",
subtitle: "Super SplashScreen")
SplashPageView(iconName: "leaf.fill",
title: "We will make",
subtitle: "Great things")
SplashPageView(iconName: "link.badge.plus",
title: "Let's start",
subtitle: "With a touch")
}.tabViewStyle(PageTabViewStyle())
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct SplashPageView: View {
var iconName: String
var title: String
var subtitle: String
@State private var currentOffset:CGFloat = 0.0
var body: some View {
VStack {
Spacer()
Image(systemName: iconName)
.renderingMode(.original)
.resizable()
.frame(width: 100, height: 100, alignment: .center)
.padding(.vertical, 20)
.offset(x: currentOffset)
.animation(currentOffset == 0 ? .none : .easeInOut)
Text(title)
.font(.title2)
.padding(10)
.offset(x: currentOffset * 0.9)
.animation(currentOffset == 0 ? .none : .easeInOut)
Text(subtitle)
.font(.title)
.offset(x: currentOffset * 0.8)
.animation(currentOffset == 0 ? .none : .easeInOut)
Spacer()
}
.frame(width: UIScreen.main.bounds.size.width, alignment: .center)
.readFrame(onChange: { (newFrame) in
print(currentOffset)
currentOffset = newFrame.origin.x
})
}
}
//Based on Sharing layout information in SwiftUI
//https://fivestars.blog/swiftui/swiftui-share-layout-information.html
extension View {
func readSize(onChange: @escaping (CGSize) -> Void) -> some View {
background(
GeometryReader { geometryProxy in
Color.clear
.preference(key: SizePreferenceKey.self, value: geometryProxy.size)
}
)
.onPreferenceChange(SizePreferenceKey.self, perform: onChange)
}
func readFrame(onChange: @escaping (CGRect) -> Void) -> some View {
background(
GeometryReader { geometryProxy in
Color.clear
.preference(key: RectPreferenceKey.self, value: geometryProxy.frame(in: CoordinateSpace.global))
}
)
.onPreferenceChange(RectPreferenceKey.self, perform: onChange)
}
}
private struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {}
}
private struct RectPreferenceKey: PreferenceKey {
static var defaultValue: CGRect = .zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment