Skip to content

Instantly share code, notes, and snippets.

@vibrazy
Created July 12, 2020 16:01
Show Gist options
  • Save vibrazy/a1cd6577528c0fd0574581f2831d8831 to your computer and use it in GitHub Desktop.
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.
//
// 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