Created
July 12, 2020 16:01
-
-
Save vibrazy/a1cd6577528c0fd0574581f2831d8831 to your computer and use it in GitHub Desktop.
iOS 14, `ScrollViewReader` + `TabView`, rough around the edges but you get the idea.
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
// | |
// TilingTabView.swift | |
// | |
// | |
// Created by Dan Tavares on 12/07/2020. | |
// | |
import SwiftUI | |
class State: ObservableObject { | |
@Published var itemIndex: Int = 0 | |
@Published var color: Color = .white | |
} | |
struct TilingTabView: View { | |
@StateObject var state = State() | |
enum Options { | |
static var animation = Animation.spring() | |
static var pillColor = Color.black | |
static var pillTitleColorSelected = Color.white | |
static var pillTitleColorNormal = Color.black | |
static var rows = [GridItem(.flexible())] | |
static var scrollToPosition = UnitPoint.center | |
} | |
let items: [String] = [ | |
"Item 1", | |
"Item 2", | |
"Item 3", | |
"Item 4", | |
"Item 5", | |
"Item 6", | |
"Item 7" | |
] | |
func scrollTo(index: Int, scrollProxy: ScrollViewProxy) { | |
scrollProxy.scrollTo(items[index], anchor: Options.scrollToPosition) | |
} | |
var body: some View { | |
ZStack { | |
state.color.edgesIgnoringSafeArea(.all) | |
VStack { | |
ScrollViewReader { scrollProxy in | |
// Title Scroll View | |
ScrollView(.horizontal, showsIndicators: false) { | |
LazyHGrid(rows: Options.rows, alignment: .top) { | |
ForEach(items.enumeratedArray(), id: \.element) { index, text in | |
Button(action: { | |
withAnimation(Options.animation) { | |
state.itemIndex = index | |
scrollTo(index: index, scrollProxy: scrollProxy) | |
} | |
}) { | |
Text("\(text)") | |
.bold() | |
.foregroundColor(state.itemIndex == index ? Options.pillTitleColorSelected : Options.pillTitleColorNormal) | |
.padding(.horizontal) | |
.padding(.vertical, 8) | |
.background(state.itemIndex == index ? Options.pillColor : Color.clear) | |
.animation(Options.animation) | |
.clipShape(Capsule()) | |
} | |
} | |
} | |
.padding(.leading) | |
.onReceive(state.$itemIndex) { index in | |
withAnimation(Options.animation) { | |
state.color = Color( | |
hue: Double.random(in: 0...1), | |
saturation: Double.random(in: 0...0.5), | |
brightness: 1 | |
) | |
scrollTo(index: index, scrollProxy: scrollProxy) | |
} | |
} | |
} | |
.fixedSize(horizontal: false, vertical: true) | |
// Main Tabs Scrollview | |
TabView(selection: $state.itemIndex) { | |
ForEach(items.enumeratedArray(), id: \.element) { index, text in | |
Text("\(text)") | |
.font(.largeTitle) | |
.tag(index) | |
} | |
} | |
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) | |
Spacer() | |
} | |
} | |
} | |
} | |
} | |
extension Collection { | |
func enumeratedArray() -> Array<(offset: Int, element: Self.Element)> { | |
return Array(self.enumerated()) | |
} | |
} | |
struct TilingTabView_Previews: PreviewProvider { | |
static var previews: some View { | |
TilingTabView() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment