Skip to content

Instantly share code, notes, and snippets.

@alemar11
Forked from fabiogiolito/InstaStories.swift
Created June 30, 2019 11:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alemar11/7886b0f3f298e628e67a009487ae7c01 to your computer and use it in GitHub Desktop.
Save alemar11/7886b0f3f298e628e67a009487ae7c01 to your computer and use it in GitHub Desktop.
Instagram Stories in SwiftUI. Demo video: https://twitter.com/fabiogiolito/status/1142924688525529088
//
// InstaStories.swift
// SwiftUITests
//
// Created by Fabio Giolito on 23/06/2019.
// Copyright © 2019 Fabio Giolito. All rights reserved.
//
import Combine
import SwiftUI
struct Story: Identifiable {
var id: Int
var user: String
var videos: [Int]
}
struct InstaStories : View {
var stories = [
Story(id: 0, user: "cat", videos: [0, 1, 2]),
Story(id: 1, user: "hand", videos: [0, 1, 2, 3]),
Story(id: 2, user: "man", videos: [0, 1])
]
@State var currentStory: Int = 0
@State var currentVideo: Int = 0
var body: some View {
ZStack {
ForEach(stories.reversed()) { story in
ZStack {
ForEach(story.videos.identified(by: \.self)) { video in
Image("Story\(story.id)Video\(video)").resizable()
.opacity(self.isVisible(story: story.id, video: video) ? 1 : 0)
}
// Overlay UI
VStack {
HStack {
ForEach(story.videos.identified(by: \.self)) { video in
ZStack(alignment: .leading) {
if (self.isVisible(story: story.id, video: video)) {
Rectangle()
}
Rectangle().opacity(0.3)
}.frame(height: 4).cornerRadius(2)
}
}
AvatarBar(userAvatar: story.user, userName: story.user)
Spacer()
CommentsBar()
}
.foregroundColor(.white)
.padding()
}.offset(x: CGFloat(story.id - self.currentStory) * UIScreen.main.bounds.width)
.animation(.fluidSpring())
}
// Navigation buttons
HStack {
Rectangle().opacity(0).tapAction { self.prevVideo() }
Rectangle().opacity(0).tapAction { self.nextVideo() }
}
}.cornerRadius(20).clipped()
}
func isVisible(story: Int, video: Int) -> Bool {
if (video == 0) { return true }
if (story < currentStory || (story == currentStory && video <= currentVideo)) { return true }
return false
}
func prevVideo() {
if (currentVideo > 0) {
currentVideo -= 1
} else if (currentStory > 0) {
currentStory -= 1
currentVideo = stories[currentStory].videos.count - 1
print("prev story")
} else {
print("at lower limit")
}
}
func nextVideo() {
if (currentVideo < stories[currentStory].videos.count - 1) {
currentVideo += 1
} else if (currentStory < stories.count - 1) {
currentStory += 1
currentVideo = 0
print("next story")
} else {
print("at top limit")
}
}
}
struct AvatarBar : View {
var userAvatar: String
var userName: String
var body: some View {
HStack {
Image(userAvatar).resizable().frame(width: 40, height: 40)
Text(userName)
Spacer()
Image(systemName: "xmark")
}
}
}
struct CommentsBar : View {
var body: some View {
HStack {
HStack {
Image(systemName: "camera.fill")
}
.frame(width: 40, height: 40)
.border(Color.white, width: 1, cornerRadius: 20)
HStack {
Text("Send message")
Spacer()
Image(systemName: "ellipsis")
}
.padding(.horizontal)
.frame(height: 40)
.border(Color.white, width: 1, cornerRadius: 20)
Image(systemName: "paperplane").imageScale(.large)
}
}
}
#if DEBUG
struct InstaStories_Previews : PreviewProvider {
static var previews: some View {
InstaStories()
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment