π΄ Let's Build Twitter with SwiftUI (iOS 15, Xcode 13, Firebase, SwiftUI 3.0)
SideMenuView()
.frame(width: 300)
.offset(x: showMenu ? 0 : -300, y: 0)
.background(showMenu ? Color.white : Color.clear)
showMenu
κ° @State
νλ‘νΌν°μ΄κΈ° λλ¬Έμ κ΄μ°° κ°λ₯, νμ¬ μν©μ λ§μ· x
κ° λ³κ²½.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation(.easeInOut) {
showMenu.toggle()
}
} label: {
Circle()
.frame(width: 32, height: 32)
}
}
}
ForEach(SideMenuViewModel.allCases, id:\.rawValue) { viewModel in
if viewModel == .profile {
SideMenuOptionRowView(viewModel: viewModel)
.onTapGesture {
showProfileView.toggle()
}
} else if viewModel == .logout {
SideMenuOptionRowView(viewModel: viewModel)
.onTapGesture {
print("Handle logout here...")
}
} else {
SideMenuOptionRowView(viewModel: viewModel)
}
}
.background(NavigationLink(destination: ProfileView(), isActive: $showProfileView, label: {
EmptyView()
}))
showProfileView
νλ‘νΌν° κ°μ΄ μ°ΈμΌ λμλ§ μ΄λμ
λΌμ΄μ¦ ν νΈμimport SwiftUI
@main
struct TwitterCloneApp: App {
var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
}
}
}
}
import SwiftUI
struct ContentView: View {
@State private var showMenu: Bool = false
var body: some View {
ZStack(alignment: .topLeading) {
MainTabView()
.navigationBarHidden(showMenu)
if showMenu {
ZStack {
Color(.black)
.opacity(showMenu ? 0.25 : 0)
.onTapGesture {
withAnimation(.easeInOut) {
showMenu = false
}
}
}
.ignoresSafeArea()
}
SideMenuView()
.frame(width: 300)
.offset(x: showMenu ? 0 : -300, y: 0)
.background(showMenu ? Color.white : Color.clear)
}
.navigationTitle("Home")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation(.easeInOut) {
showMenu.toggle()
}
} label: {
Circle()
.frame(width: 32, height: 32)
}
}
}
.onAppear {
showMenu = false
}
}
}
@State
λ‘ μ μΈν νλ‘νΌν° κ° λ³κ²½μ κ΄μ°° κ°λ₯νκΈ° λλ¬Έμ μ λλ©μ΄μ
κ°λ₯import SwiftUI
struct SideMenuView: View {
@State private var showProfileView: Bool = false
var body: some View {
ZStack {
VStack(alignment: .leading, spacing: 32) {
VStack(alignment: .leading) {
Circle()
.frame(width: 48, height: 48)
VStack(alignment: .leading, spacing: 4) {
Text("Peter Parker")
.font(.headline)
Text("@SpiderMan")
.font(.caption)
.foregroundColor(.gray)
}
UserStatsView()
.padding(.vertical)
}
.padding(.leading)
ForEach(SideMenuViewModel.allCases, id:\.rawValue) { viewModel in
if viewModel == .profile {
SideMenuOptionRowView(viewModel: viewModel)
.onTapGesture {
showProfileView.toggle()
}
} else if viewModel == .logout {
SideMenuOptionRowView(viewModel: viewModel)
.onTapGesture {
print("Handle logout here...")
}
} else {
SideMenuOptionRowView(viewModel: viewModel)
}
}
Spacer()
}
}
.background(NavigationLink(destination: ProfileView(), isActive: $showProfileView, label: {
EmptyView()
}))
}
}
isActive
λ₯Ό ν΅ν΄ λ€λΉκ²μ΄μ
λ·° λ°μΈλ©import SwiftUI
struct SideMenuOptionRowView: View {
let viewModel: SideMenuViewModel
var body: some View {
HStack(spacing: 16) {
Image(systemName: viewModel.imageName)
.font(.headline)
.foregroundColor(.gray)
Text(viewModel.title)
.font(.subheadline)
Spacer()
}
.frame(height: 40)
.padding(.horizontal)
.background(Color(.systemBackground).opacity(0.001))
}
}