Created
March 26, 2021 11:52
-
-
Save valvoline/cd426ae3f82f7b5bfb0b28703c35507c to your computer and use it in GitHub Desktop.
A simple Parallax Effect based paged ScrollView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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