Last active
May 6, 2024 17:10
-
-
Save Arutyun2312/01e8ef11dc69ef4cf1c095b215cd1f12 to your computer and use it in GitHub Desktop.
Custom Geometry Reader
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
// | |
// 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) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.