Skip to content

Instantly share code, notes, and snippets.

@Arutyun2312
Last active May 6, 2024 17:10
Show Gist options
  • Save Arutyun2312/01e8ef11dc69ef4cf1c095b215cd1f12 to your computer and use it in GitHub Desktop.
Save Arutyun2312/01e8ef11dc69ef4cf1c095b215cd1f12 to your computer and use it in GitHub Desktop.
Custom Geometry Reader
//
// CustomGeometryReader.swift
//
//
// Created by Arutyun Enfendzhyan on 10.01.22.
//
import SwiftUI
struct CustomGeometryReader: View {
@Binding var rect: CGRect
@StateObject var view = ResisableUIView()
var body: some View {
Impl(view: view)
.onReceive(view.$rect) { rect = $0 }
}
struct Impl: UIViewRepresentable {
typealias UIViewType = CustomGeometryReader.ResisableUIView
let view: UIViewType
func makeUIView(context: Context) -> UIViewType { view }
func updateUIView(_ uiView: UIViewType, context: Context) {}
}
final class ResisableUIView: UIView, ObservableObject {
@Published var rect = CGRect.zero
override func layoutSubviews() {
super.layoutSubviews()
rect = convert(frame, to: nil)
}
}
}
public extension View {
func frame(reader: Binding<CGRect>) -> some View { background(CustomGeometryReader(rect: reader)) }
func frame(reader: Binding<CGSize>) -> some View {
frame(reader: .init { .init(origin: .zero, size: reader.wrappedValue) } set: { reader.wrappedValue = $0.size })
}
func frame(reader: Binding<CGPoint>) -> some View {
frame(reader: .init { .init(origin: reader.wrappedValue, size: .zero) } set: { reader.wrappedValue = $0.origin })
}
}
// MARK: Example Usage
struct CustomGeometryReader_Previews: PreviewProvider, View, Init {
@State var rect = CGRect.zero
var body: some View {
VStack {
Text("\(rect)" as String)
Color.blue
.frame(width: 100, height: 100)
.frame(reader: $rect)
.padding(.leading)
}
}
}
@Arutyun2312
Copy link
Author

Arutyun2312 commented Jan 10, 2022

Apple's GeometryReader couldn't be more complicated, whenever I needed to obtain the size of a view. Therefore I decided to create CustomGeometryReader, where instead of using preferences to pass around the frame, just use a state. Although it lacks the coordinate space, it's an easy workaround, use multiple CustomGeometryReaders. Maybe I will add it in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment