Skip to content

Instantly share code, notes, and snippets.

@mattyoung
Last active July 23, 2020 16:01
Show Gist options
  • Save mattyoung/399c9844be0b260149c7968344525c29 to your computer and use it in GitHub Desktop.
Save mattyoung/399c9844be0b260149c7968344525c29 to your computer and use it in GitHub Desktop.
//
// PlayButtonOffsetProblem.swift
// NewWorld12
//
// Created by Matthew on 7/21/20.
//
import SwiftUI
/// A ViewModifier to offset a view by x, y computed from the view's GeometryProxy
///
/// Example: to optically center align Image(systemName: "play") by centering on
/// the enclosing circle of the equilateral triangle, the diameter of the circle
/// is 4/3 * triagle-width, shift amount (4/3 - 1)/2/2 = 1/12
///
/// Image(systemName: "play")
/// .foregroundColor(.white)
/// .font(.system(size: 80))
/// .modifier(Offset(by: { CGSize(width: $0.size.width / 12, height: 0.0) })) // shift right 1/12 the width
struct Offset: PreferenceKey, ViewModifier {
// caller calculate offset x, y value giving the view's GeometryProxy
let by: (GeometryProxy) -> CGSize
static var defaultValue = CGSize(width: 0.0, height: 0.0)
static func reduce(value: inout Value, nextValue: () -> Value) {
value = nextValue()
}
@State private var offset = CGSize(width: 0.0, height: 0.0)
func body(content: Content) -> some View {
content
.background(
GeometryReader {
Color.clear
.preference(key: Self.self, value: by($0))
}
)
.offset(offset)
.onPreferenceChange(Self.self) { offset = $0 }
}
}
extension View {
func offset(by: @escaping (GeometryProxy) -> CGSize) -> some View {
self.modifier(Offset(by: by))
}
}
struct PlayButtonOffsetProblem: View {
static private let buttonSize: CGFloat = 55
var body: some View {
ZStack {
VStack {
Button { }
label: {
Circle()
.frame(width: Self.buttonSize, height: Self.buttonSize)
.overlay(
Image(systemName: "play")
.foregroundColor(.white)
.font(.largeTitle)
// .border(Color.black, width: 1)
)
}
Button { }
label: {
Circle()
.frame(width: Self.buttonSize, height: Self.buttonSize)
.overlay(
Image(systemName: "play")
.foregroundColor(.white)
.font(.largeTitle)
.offset(by: { CGSize(width: $0.size.width / 12, height: 0.0) })
// .border(Color.black, width: 1)
)
}
Button { }
label: {
Circle()
.frame(width: Self.buttonSize * 2, height: Self.buttonSize * 2)
.overlay(
Image(systemName: "play")
.foregroundColor(.white)
.font(.system(size: 80))
// .border(Color.black, width: 1)
)
}
Button { }
label: {
Circle()
.frame(width: Self.buttonSize * 2, height: Self.buttonSize * 2)
.overlay(
Image(systemName: "play")
.foregroundColor(.white)
.font(.system(size: 80))
.offset(by: { CGSize(width: $0.size.width / 12, height: 0.0) })
// .border(Color.black, width: 1)
)
}
Button { }
label: {
Circle()
.frame(width: Self.buttonSize, height: Self.buttonSize)
.overlay(
Image(systemName: "stop")
.foregroundColor(.white)
.font(.largeTitle)
)
}
Button { }
label: {
Circle()
.frame(width: Self.buttonSize, height: Self.buttonSize)
.overlay(
Image(systemName: "play.circle")
.foregroundColor(.white)
.font(.largeTitle)
)
}
}
Color.green
.frame(width: 1, height: 600, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
}
}
}
struct PlayButtonOffsetProblem_Previews: PreviewProvider {
static var previews: some View {
PlayButtonOffsetProblem()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment