Created
February 6, 2023 02:09
-
-
Save AdamWhitcroft/085bf4e81cb08d9528cfcceb7e0fee7c to your computer and use it in GitHub Desktop.
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
struct Overlay: View { | |
@State private var showLive = true | |
@State private var isAnimationSlowed = false | |
var body: some View { | |
VStack { | |
Spacer() | |
HStack { | |
Spacer() | |
Pill( | |
showLive: $showLive, | |
isAnimationSlowed: $isAnimationSlowed | |
) | |
} | |
.padding() | |
Spacer() | |
Button { | |
isAnimationSlowed.toggle() | |
} label: { | |
Text(isAnimationSlowed ? "Fast animation" : "Slow animation") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
} | |
} | |
} | |
} | |
private struct Pill: View { | |
@Binding var showLive: Bool | |
@Binding var isAnimationSlowed: Bool | |
let debugAnimation: Animation = .easeOut(duration: 2) | |
let animation: Animation = .interpolatingSpring(mass: 0.5, stiffness: 300, damping: 20) | |
var body: some View { | |
ZStack(alignment: .leading) { | |
HStack { | |
// | |
// circle shape | |
// | |
Circle() | |
.fill(.clear) | |
.frame(width: 30, height: 30) | |
.overlay { | |
ZStack { | |
ViewerCountIcon() | |
.opacity(showLive ? 1 : 0) | |
ViewerAvatar() | |
.opacity(showLive ? 0 : 1) | |
} | |
} | |
.overlay(alignment: .leading) { | |
// | |
// these are the visible labels | |
// we're overlaying on the circle | |
// because the circle is the only | |
// thing that's actually changing position | |
// | |
ZStack(alignment: .leading) { | |
TextViewOne() | |
.opacity(showLive ? 1 : 0) | |
TextViewTwo() | |
.opacity(showLive ? 0 : 1) | |
} | |
.frame(width: 200, alignment: .leading) | |
.padding(.leading, 38) | |
} | |
// | |
// we're using these views to give us the correct | |
// widths for our content in each state, even | |
// though we're not actually seeing them | |
// | |
if showLive { | |
TextViewOneSizer() | |
} else { | |
TextViewTwoSizer() | |
} | |
} | |
.onTapGesture { | |
withAnimation(isAnimationSlowed ? debugAnimation : animation) { | |
showLive.toggle() | |
} | |
} | |
} | |
.padding(8) | |
.padding(.trailing, 4) | |
.background(.ultraThinMaterial) | |
.clipShape(RoundedRectangle(cornerRadius: 24)) | |
} | |
} | |
// | |
// make sure `TextViewOne` and `TextViewOneSizer` | |
// have the same content, can be generated dynamically | |
// | |
private struct TextViewOne: View { | |
var body: some View { | |
Text("32") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
} | |
} | |
private struct TextViewOneSizer: View { | |
var body: some View { | |
Text("32") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
.foregroundColor(.clear) | |
} | |
} | |
// | |
// make sure `TextViewTwo` and `TextViewTwoSizer` | |
// have the same content, can be generated dynamically | |
// | |
private struct TextViewTwo: View { | |
var body: some View { | |
Group { | |
Text("Mike is in this ") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
+ | |
Text("live!") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
.foregroundColor(.green) | |
} | |
} | |
} | |
private struct TextViewTwoSizer: View { | |
var body: some View { | |
Group { | |
Text("Mike is in this live!") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
.foregroundColor(.clear) | |
} | |
} | |
} | |
private struct ViewerCountIcon: View { | |
var body: some View { | |
Circle() | |
.fill(.red) | |
.frame(width: 30, height: 30) | |
.overlay { | |
Image(systemName: "lines.measurement.horizontal") | |
.font(.system(.body, design: .rounded).weight(.medium)) | |
.foregroundColor(.white) | |
} | |
} | |
} | |
private struct ViewerAvatar: View { | |
var body: some View { | |
Circle() | |
.fill(.yellow.opacity(0.5)) | |
.frame(width: 30, height: 30) | |
.overlay { | |
Text("😀") | |
} | |
} | |
} | |
struct Overlay_Previews: PreviewProvider { | |
static var previews: some View { | |
Overlay() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment