{"componentChunkName":"component---src-templates-article-js","path":"/article/geometryreader-overview","result":{"data":{"contentfulArticle":{"title":"GeometryReader Overview for Beginners","image":"https://res.cloudinary.com/liquidcoder/image/upload/v1613639241/Overview%20blog%20posts/GeometryReader/njefjbh9tpi1pvomsvyq.jpg","createdDate":"Thursday, 18 February 2021","videoUrl":null,"updatedDate":"2 years ago","isNewLayout":true,"previews":{"previews":"{\n    \"GRContentView1\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613477482/Overview%20blog%20posts/Shared/ziohvs60zjkqxnenf4zl.png\" ],\n    \"GRContentView2\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613479170/Overview%20blog%20posts/GeometryReader/hp9cyrmilrr0gsfkt9z0.png\" ],\n    \"GRContentView3\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613481623/Overview%20blog%20posts/GeometryReader/fml7lyux8cz4pmjylquf.png\" ],\n    \"GRContentView4\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613483436/Overview%20blog%20posts/GeometryReader/ikjsr8kuxbjhna2o8gfa.png\" ],\n    \"GRContentView5\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613484168/Overview%20blog%20posts/GeometryReader/jihkn2url4cwncy6wvs5.png\" ],\n    \"GRContentView6\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613485460/Overview%20blog%20posts/GeometryReader/tzbmafzttmbqqcxp1hbz.png\" ],\n    \"GRContentView7\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613487612/Overview%20blog%20posts/GeometryReader/hv7pxrxpqvlfzhhx2nww.png\" ],\n    \"GRContentView8\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613649075/Overview%20blog%20posts/GeometryReader/osle9qryiksaulqmdykn.png\" ],\n    \"GRContentView9\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613489759/Overview%20blog%20posts/GeometryReader/nawmaka1ubxescseyrqx.png\" ],\n    \"GRContentView10\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613502443/Overview%20blog%20posts/GeometryReader/dlylltand2vyf7vnaujk.png\" ],\n    \"GRContentView11\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613503558/Overview%20blog%20posts/GeometryReader/uieovnh1q2vgps43kfqm.gif\" ],\n    \"GRContentView12FinalDemo2\": [ \"https://res.cloudinary.com/liquidcoder/image/upload/v1613640167/Overview%20blog%20posts/GeometryReader/mgzz0e9oscdlfwdit7eb.gif\" ]\n}"},"slug":"geometryreader-overview","author":{"email":"john@liquidcoder.com","name":"John"},"tags":[{"title":"Swift UI"},{"title":"Free"},{"title":"iOS App Development"}],"allChapters":["GRContentViewIntro:Introduction","GRContentViewGeometryProxy1:GeometryProxy","GRContentViewUseCasesIntro1:Use cases"],"code":{"childMdx":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentViewIntro\\n\\n@frozen struct GeometryReader<Content> where Content : View\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView1\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        Text(\\\"Hello, World!\\\")\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView2\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            Text(\\\"Hello, World!\\\")\\n                .border(Color.blue)\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView3\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            Text(\\\"Hello, World!\\\")\\n                .border(Color.blue)\\n\\n            Text(\\\"Green\\\")\\n                .border(Color.green)\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView4\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading)  {\\n                VStack(alignment: .leading)  {\\n                    Text(\\\"Height : \\\\(geometry.size.height)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Width : \\\\(geometry.size.width)\\\")\\n                        .padding()\\n                }\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView5\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            VStack(alignment: .leading)  {\\n                VStack(alignment: .leading)  {\\n                    Text(\\\"Height : \\\\(geometry.size.height)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Width : \\\\(geometry.size.width)\\\")\\n                        .padding()\\n                }\\n            }\\n\\n        }.border(Color.red)\\n        // highlight-start\\n        .frame(width: 300, height: 400)\\n        // highlight-end\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView6\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n\\n                Text(\\\"Global origin X : \\\\(geometry.frame(in: .global).origin.x)\\\")\\n                    .padding()\\n\\n                Text(\\\"Global origin Y : \\\\(geometry.frame(in: .global).origin.y)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local origin X : \\\\(geometry.frame(in: .local).origin.x)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local origin Y : \\\\(geometry.frame(in: .local).origin.y)\\\")\\n                    .padding()\\n            }\\n\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView7\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n                Text(\\\"Safe area top : \\\\(geometry.safeAreaInsets.top)\\\")\\n                    .padding()\\n\\n                Text(\\\"Safe area bottom : \\\\(geometry.safeAreaInsets.bottom)\\\")\\n                    .padding()\\n\\n                Text(\\\"Safe area leading : \\\\(geometry.safeAreaInsets.leading)\\\")\\n                    .padding()\\n\\n                Text(\\\"Safe area trailing : \\\\(geometry.safeAreaInsets.trailing)\\\")\\n                    .padding()\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView8\\n// $$liquidcoderFilename-ContentView\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            VStack(alignment: .leading) {\\n\\n                VStack(alignment: .leading) {\\n\\n                    Text(\\\"Global min X : \\\\(geometry.frame(in: .global).minX)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Global min Y : \\\\(geometry.frame(in: .global).minY)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Local min X : \\\\(geometry.frame(in: .local).minX)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Local min Y : \\\\(geometry.frame(in: .local).minY)\\\")\\n                        .padding()\\n                }\\n\\n                Text(\\\"MAX = MIN + SIZE\\\")\\n                    .bold()\\n                    .padding()\\n\\n                VStack(alignment: .leading) {\\n\\n                    Text(\\\"Global max X : \\\\(geometry.frame(in: .global).maxX)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Global max Y : \\\\(geometry.frame(in: .global).maxY)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Local max X : \\\\(geometry.frame(in: .local).maxX)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Local max Y : \\\\(geometry.frame(in: .local).maxY)\\\")\\n                        .padding()\\n                }\\n            }\\n\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"div\", {\n    id: \"GRContentViewMinMaxExplain1\",\n    className: \"code-block\"\n  }, mdx(\"div\", {\n    className: \"end-result\"\n  }, mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613574683/Overview%20blog%20posts/GeometryReader/o5tltnbecgcglmmur1yt.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613574683/Overview%20blog%20posts/GeometryReader/o5tltnbecgcglmmur1yt.png\"\n  }))))), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView9\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n                Text(\\\"Global MidX : \\\\(geometry.frame(in: .global).midX)\\\")\\n                    .padding()\\n\\n                Text(\\\"Global MidY : \\\\(geometry.frame(in: .global).midY)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local MidX : \\\\(geometry.frame(in: .local).midX)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local MidY : \\\\(geometry.frame(in: .local).midY)\\\")\\n                    .padding()\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView10\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            Image(\\\"image\\\")\\n                .resizable()\\n                .scaledToFit()\\n                // highlight-start\\n                .frame(width: geometry.size.width * 0.7, height: geometry.size.height * 0.4)\\n                .offset(x: (geometry.size.width - (geometry.size.width * 0.7)) / 2, y: 0)\\n                // highlight-end\\n        }.border(Color.red)\\n    }\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView11\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var body: some View {\\n        ScrollView {\\n            ForEach(0 ..< 15) { item in\\n                GeometryReader { geometry in\\n                    // highlight-start\\n                    Text(\\\"\\\"\\\"\\n                            Global X: \\\\(geometry.frame(in: .global).minX) \\\\n\\n                            Global Y: \\\\(geometry.frame(in: .global).minY) \\\\n\\n                            Local X: \\\\(geometry.frame(in: .local).minX) \\\\n\\n                            Local Y: \\\\(geometry.frame(in: .local).minY) \\\\n\\n                            \\\"\\\"\\\")\\n                        // highlight-end\\n                        .frame(width: geometry.size.width * 0.7, height: geometry.size.height )\\n                        .offset(x: (geometry.size.width - (geometry.size.width * 0.7)) / 2, y: 0)\\n\\n                }.frame(height: 400)\\n            }\\n        }\\n    } \\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView12FinalDemo1\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    // highlight-start\\n    var screenHeight = UIScreen.main.bounds.height\\n    var screenWidth = UIScreen.main.bounds.width\\n    // highlight-end\\n\\n    var body: some View {\\n        ScrollView {\\n            ForEach(0 ..< 15) { item in\\n                GeometryReader { geometry in\\n                    // highlight-start\\n                    createImage(geometry: geometry)\\n                    // highlight-end\\n                }.frame(height: 700)\\n            }\\n        }\\n    }\\n\\n    // highlight-start\\n    private func createImage(geometry: GeometryProxy) -> some View {\\n\\n    }\\n    // highlight-end\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderID-GRContentView12FinalDemo2\\n// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var screenHeight = UIScreen.main.bounds.height\\n    var screenWidth = UIScreen.main.bounds.width\\n\\n    var body: some View {\\n        ScrollView {\\n            ForEach(0 ..< 15) { item in\\n                GeometryReader { geometry in\\n                    createImage(geometry: geometry)\\n                }.frame(height: 700)\\n            }\\n        }\\n    }\\n\\n    private func createImage(geometry: GeometryProxy) -> some View {\\n\\n        // highlight-start\\n        let height = geometry.size.height\\n        let minY = geometry.frame(in: .global).minY\\n\\n        let scrolledInterval = max(0, min(minY, screenHeight))\\n        let scrolledPercent = scrolledInterval / screenHeight\\n\\n        return Image(\\\"image\\\")\\n            .resizable()\\n            .frame(width: screenWidth, height: height - (height * scrolledPercent) )\\n            .rotation3DEffect(\\n                Angle(degrees: 70 * Double(scrolledPercent)) ,\\n                axis: (x: 1.0, y: 0.0, z: 0.0),\\n                anchorZ: 0.0,\\n                perspective: -1.0\\n            ).scaleEffect(1.0 - scrolledPercent)\\n        // highlight-end\\n    }\\n}\\n\")));\n}\n;\nMDXContent.isMDXComponent = true;"}},"explanation":{"childMdx":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"div\", {\n    id: \"GRContentViewIntro-Section\",\n    className: \"post-section\"\n  }, mdx(\"h2\", null, \"GeometryReader Introduction\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Apple says: \\\"A container view that defines its content as a function of its own size and coordinate space. This view returns a flexible preferred size to its parent layout.\\\"\")), mdx(\"p\", null, \"In simple term, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" is a container that will fill the available space, unless given a fixed frame, and will provide its children with the exact size (width and height) that it occupies as well as its coordinates space (X-Origin and Y-Origin).\")), mdx(\"div\", {\n    id: \"GRContentView1-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"Consider the following example code, as you see the text is perfectly centered with its size matching its content.\"), mdx(\"p\", null, \"Let's now surround that text with a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" container, and see what happens.\")), mdx(\"div\", {\n    id: \"GRContentView2-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"Oops! The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Text\"), \" is not centred anymore. This is because \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" align its children's with its origin (\", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"x = 0, y=0\"), \"). \"), mdx(\"p\", null, \"The other thing to note is that the container does not completely fill the entire screen, the top and bottom spaces accommodate the safe areas, so technically those space are not part of the usable screen unless ignored. \")), mdx(\"div\", {\n    id: \"GRContentView3-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"No matter how many children you add inside, they will all be stacked on top of each other aligned with the parent's origin. \")), mdx(\"div\", {\n    id: \"GRContentViewGeometryProxy1-Section\",\n    className: \"post-section\"\n  }, mdx(\"h2\", null, \"GeometryProxy\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Apple says:\\\"A proxy for access to the size and coordinate space (for anchor resolution) of the container view.\\\"\"))), mdx(\"div\", {\n    id: \"GRContentView4-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" will give us an object of type \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \" upon initialisation that contains its size and coordinate space.\"), mdx(\"p\", null, \"Now, let's change the frame and see what happens.\")), mdx(\"div\", {\n    id: \"GRContentView5-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"As you can see the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"height\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"width\"), \" on the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \" have changed reflecting the same values we set using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"frame\"), \" modifier.\"), mdx(\"p\", null, \"Next, let's take a look to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \"'s \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"frame\"), \" .\")), mdx(\"div\", {\n    id: \"GRContentView6-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"frame\"), \" function returns a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"CGRect\"), \" type that contains a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"size\"), \" and an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"origin\"), \".\"), mdx(\"p\", null, \"Taking a look at the preview, you can see that the Global origin Y is different from the Local origin Y, the global origin is relative to the parent whereas the local one is relative to itself.\")), mdx(\"div\", {\n    id: \"GRContentView7-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"You can also get access to the safe area insets directly from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \" object, and a you will get valid values if there's no fixed frame applied to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" .\")), mdx(\"div\", {\n    id: \"GRContentView8-Section\",\n    className: \"post-section\"\n  }, mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Apple says: \\\"Returns the smallest value for the x-coordinate of the rectangle.\\\"\")), mdx(\"p\", null, \"Those properties have their \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"max\"), \" equivalent that return the largest coordinates rather than smallest.\")), mdx(\"div\", {\n    id: \"GRContentViewMinMaxExplain1-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"Check out the illustration on the right which shows where those min and max coordinates are located.\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Here is how they are calculated:\"), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"minX = origin.x\")), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"minY = origin.y\")), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"maxX = origin.x + size.width\")), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"maxY = origin.y + size.height\")))), mdx(\"div\", {\n    id: \"GRContentView9-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"CGRect\"), \" object returned by the frame also has mid-coordinates (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"midX\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"midY\"), \") which are the center coordinates of the rectangle constructed by the 4 points we've just talked about.\")), mdx(\"div\", {\n    id: \"GRContentViewUseCasesIntro1-Section\",\n    className: \"post-section\"\n  }, mdx(\"h2\", null, \"Use cases\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" can be daunting when you first start working with it, but once you get acquainted with its few rules, you will find that it's quite a fun feature to play with, and most importantly very powerful.\")), mdx(\"div\", {\n    id: \"GRContentViewUseCasesIntro2-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"Take an example where you want to make a view's size be a fraction of its parent, and be centered along the x or y axis. This can be a tough challenge without using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"))), mdx(\"div\", {\n    id: \"GRContentView10-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"We use an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Image\"), \" view as an example. We will center it along the x axis (horizontally), so we are only interested in the width, not the height.\"), mdx(\"p\", null, \"We give the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Image\"), \" a width equal to 70% of the parent, then apply an horizontal offset equal to half of the difference between the parent's width and the child's. This will center the image no matter the parent's width.\")), mdx(\"div\", {\n    id: \"GRContentView11-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"Take a look at this next example... We put a list of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" containers inside a scrollview. Note that we need to give each of them a fixed height for it to be displayed properly.\"), mdx(\"p\", null, \"When you scroll, you will see that only the global \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"minY\"), \" changes. There are 2 reasons for that:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"The default scroll \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"axis\"), \" is \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"vertical\"), \", so only y values are changing.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"The global coordinates are relative to the device's screen which means they reflect the origin position in the screen's rectangle.\"))), mdx(\"div\", {\n    id: \"GRContentView12FinalDemo1-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"For the final demo, we need the entire device screen height and width. We then replace the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Text\"), \" view with the call to that \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createImage\"), \" function created a little bit down.\"), mdx(\"p\", null, \"Now let's do the remaining work in that function.\")), mdx(\"div\", {\n    id: \"GRContentView12FinalDemo2-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, \"The main component that makes the effect possible is the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"minY\"), \" from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \"'s frame which is the only dynamic variable in this case.\")), mdx(\"div\", {\n    id: \"GRContentView12Outro-Section\",\n    className: \"post-section\"\n  }, mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" is one of the most powerful features in swiftUI. One can create amazing effects with it, and sky is the only limit really. See you in the next overview. Happy coding!\")));\n}\n;\nMDXContent.isMDXComponent = true;"}},"downloads":null,"resources":[{"name":"Apple developer documentation","url":"https://developer.apple.com/documentation/swiftui/geometryreader"},{"name":"GeometryReader to the Rescue","url":"https://swiftui-lab.com/geometryreader-to-the-rescue/"}],"body":{"childMdx":{"tableOfContents":{"items":[{"url":"#geometryproxy","title":"GeometryProxy"},{"url":"#use-cases","title":"Use cases"}]},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Apple says: \\\"A container view that defines its content as a function of its own size and coordinate space. This view returns a flexible preferred size to its parent layout.\\\"\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"@frozen struct GeometryReader<Content> where Content : View\\n\")), mdx(\"p\", null, \"In simple term, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" is a container that will fill the available space, unless given a fixed frame, and will provide its children with the exact size (width and height) that it occupies as well as its coordinates space (X-Origin and Y-Origin).\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        Text(\\\"Hello, World!\\\")\\n    }\\n\\n}\\n\")), mdx(\"p\", null, \"Consider the following example code, as you see the text is perfectly centred with its size matching its content.\"), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613477482/Overview%20blog%20posts/Shared/ziohvs60zjkqxnenf4zl.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613477482/Overview%20blog%20posts/Shared/ziohvs60zjkqxnenf4zl.png\"\n  }))), mdx(\"p\", null, \"Let's now surround the text with a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" container, and what happens.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            Text(\\\"Hello, World!\\\")\\n                .border(Color.blue)\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613479170/Overview%20blog%20posts/GeometryReader/hp9cyrmilrr0gsfkt9z0.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613479170/Overview%20blog%20posts/GeometryReader/hp9cyrmilrr0gsfkt9z0.png\"\n  }))), mdx(\"p\", null, \"Oops! The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Text\"), \" is not centred anymore. This is because \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" align its children's with its origin (\", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"x = 0, y=0\"), \").  \"), mdx(\"p\", null, \"The other thing to note is that the container does not completely fill the entire screen, the top and bottom spaces  accommodate the safe areas, so technically those space are not part of the usable screen unless ignored. \"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            Text(\\\"Hello, World!\\\")\\n                .border(Color.blue)\\n\\n            Text(\\\"Green\\\")\\n                .border(Color.green)\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, \"No matter how many children you add inside, they will all be stacked on top of each other aligned with the parent's origin. \"), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613481623/Overview%20blog%20posts/GeometryReader/fml7lyux8cz4pmjylquf.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613481623/Overview%20blog%20posts/GeometryReader/fml7lyux8cz4pmjylquf.png\"\n  }))), mdx(\"h2\", null, \"GeometryProxy\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Apple says:\\\"A proxy for access to the size and coordinate space (for anchor resolution) of the container view.\\\"\")), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" will give us an object of type \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \" upon initialisation that contains its size and coordinate space.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading)  {\\n                VStack(alignment: .leading)  {\\n                    Text(\\\"Height : \\\\(geometry.size.height)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Width : \\\\(geometry.size.width)\\\")\\n                        .padding()\\n                }\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613483436/Overview%20blog%20posts/GeometryReader/ikjsr8kuxbjhna2o8gfa.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613483436/Overview%20blog%20posts/GeometryReader/ikjsr8kuxbjhna2o8gfa.png\"\n  }))), mdx(\"p\", null, \"Now, let's change the frame and see what happens.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            VStack(alignment: .leading)  {\\n                VStack(alignment: .leading)  {\\n                    Text(\\\"Height : \\\\(geometry.size.height)\\\")\\n                        .padding()\\n\\n                    Text(\\\"Width : \\\\(geometry.size.width)\\\")\\n                        .padding()\\n                }\\n            }\\n\\n        }.border(Color.red)\\n        // highlight-start\\n        .frame(width: 300, height: 400)\\n        // highlight-end\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613484168/Overview%20blog%20posts/GeometryReader/jihkn2url4cwncy6wvs5.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613484168/Overview%20blog%20posts/GeometryReader/jihkn2url4cwncy6wvs5.png\"\n  }))), mdx(\"p\", null, \"As you can see the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"height\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"width\"), \" on the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \" have changed reflecting the same values we set using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"frame\"), \" modifier.\"), mdx(\"p\", null, \"Next, let's take a look to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \"'s \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"frame\"), \" .\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n\\n                Text(\\\"Global origin X : \\\\(geometry.frame(in: .global).origin.x)\\\")\\n                    .padding()\\n\\n                Text(\\\"Global origin Y : \\\\(geometry.frame(in: .global).origin.y)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local origin X : \\\\(geometry.frame(in: .local).origin.x)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local origin Y : \\\\(geometry.frame(in: .local).origin.y)\\\")\\n                    .padding()\\n            }\\n\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613485460/Overview%20blog%20posts/GeometryReader/tzbmafzttmbqqcxp1hbz.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613485460/Overview%20blog%20posts/GeometryReader/tzbmafzttmbqqcxp1hbz.png\"\n  }))), mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"frame\"), \" function returns a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"CGRect\"), \" type which contains a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"size\"), \" and an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"origin\"), \".\"), mdx(\"p\", null, \"Taking a look at the preview, you can see that the Global origin Y is different from the Local origin Y, the global origin is relative to the parent whereas the local one is relative to itself.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n                Text(\\\"Safe area top : \\\\(geometry.safeAreaInsets.top)\\\")\\n                    .padding()\\n\\n                Text(\\\"Safe area bottom : \\\\(geometry.safeAreaInsets.bottom)\\\")\\n                    .padding()\\n\\n                Text(\\\"Safe area leading : \\\\(geometry.safeAreaInsets.leading)\\\")\\n                    .padding()\\n\\n                Text(\\\"Safe area trailing : \\\\(geometry.safeAreaInsets.trailing)\\\")\\n                    .padding()\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613487612/Overview%20blog%20posts/GeometryReader/hv7pxrxpqvlfzhhx2nww.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613487612/Overview%20blog%20posts/GeometryReader/hv7pxrxpqvlfzhhx2nww.png\"\n  }))), mdx(\"p\", null, \"You can also get access to the safe area insets directly from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryProxy\"), \" object, and a you will get valid values if there's no fixed frame applied to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" .\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n                Text(\\\"Global MinX : \\\\(geometry.frame(in: .global).minX)\\\")\\n                    .padding()\\n\\n                Text(\\\"Global MinY : \\\\(geometry.frame(in: .global).minY)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local MinX : \\\\(geometry.frame(in: .local).minX)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local MinY : \\\\(geometry.frame(in: .local).minY)\\\")\\n                    .padding()\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613489930/Overview%20blog%20posts/GeometryReader/l6zrkwwgumsmegk6x4n4.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613489930/Overview%20blog%20posts/GeometryReader/l6zrkwwgumsmegk6x4n4.png\"\n  }))), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Apple says: \\\"Returns the smallest value for the x-coordinate of the rectangle.\\\"\")), mdx(\"p\", null, \"Those properties have their \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"max\"), \" equivalent which return the largest coordinates rather than smallest.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            // highlight-start\\n            VStack(alignment: .leading) {\\n                Text(\\\"Global MidX : \\\\(geometry.frame(in: .global).midX)\\\")\\n                    .padding()\\n\\n                Text(\\\"Global MidY : \\\\(geometry.frame(in: .global).midY)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local MidX : \\\\(geometry.frame(in: .local).midX)\\\")\\n                    .padding()\\n\\n                Text(\\\"Local MidY : \\\\(geometry.frame(in: .local).midY)\\\")\\n                    .padding()\\n            }\\n            // highlight-end\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613489759/Overview%20blog%20posts/GeometryReader/nawmaka1ubxescseyrqx.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613489759/Overview%20blog%20posts/GeometryReader/nawmaka1ubxescseyrqx.png\"\n  }))), mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"CGRect\"), \" object returned by the frame also has mid-coordinates (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"midX\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"midY\"), \") which are the center coordinates  of the rectangle constructed by the 4 points we've just talked about.\"), mdx(\"p\", null, \"Check out the illustration on the right which shows where those min and max coordinates are located.\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Here is how they are calculated:\"), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"minX = origin.x\")), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"minY = origin.y\")), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"maxX = origin.x + size.width\")), mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"maxY = origin.y + size.height\"))), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613574683/Overview%20blog%20posts/GeometryReader/o5tltnbecgcglmmur1yt.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613574683/Overview%20blog%20posts/GeometryReader/o5tltnbecgcglmmur1yt.png\"\n  }))), mdx(\"h2\", null, \"Use cases\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" can be daunting when you first start working with it, but once you get acquainted with its few rules , you will find that it's quite a fun feature to play with, and most importantly very powerful.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView: View {\\n\\n    var body: some View {\\n        GeometryReader { geometry in\\n            Image(\\\"image\\\")\\n                .resizable()\\n                .scaledToFit()\\n                // highlight-start\\n                .frame(width: geometry.size.width * 0.7, height: geometry.size.height * 0.4)\\n                .offset(x: (geometry.size.width - (geometry.size.width * 0.7)) / 2, y: 0)\\n                // highlight-end\\n        }.border(Color.red)\\n    }\\n\\n}\\n\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613502443/Overview%20blog%20posts/GeometryReader/dlylltand2vyf7vnaujk.png\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613502443/Overview%20blog%20posts/GeometryReader/dlylltand2vyf7vnaujk.png\"\n  }))), mdx(\"p\", null, \"We use an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Image\"), \" view as an example. We will center it along the x axis (horizontally), so we are only interested in the width, not the height.\"), mdx(\"p\", null, \"We give the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Image\"), \" a width equal to 70% of the parent, then apply an horizontal offset equal to half of the difference between the parent's width and the child's. This will center the image no matter the parent's width.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var body: some View {\\n        ScrollView {\\n            ForEach(0 ..< 15) { item in\\n                GeometryReader { geometry in\\n                    // highlight-start\\n                    Text(\\\"\\\"\\\"\\n                            Global X: \\\\(geometry.frame(in: .global).minX) \\\\n\\n                            Global Y: \\\\(geometry.frame(in: .global).minY) \\\\n\\n                            Local X: \\\\(geometry.frame(in: .local).minX) \\\\n\\n                            Local Y: \\\\(geometry.frame(in: .local).minY) \\\\n\\n                            \\\"\\\"\\\")\\n                        // highlight-end\\n                        .frame(width: geometry.size.width * 0.7, height: geometry.size.height )\\n                        .offset(x: (geometry.size.width - (geometry.size.width * 0.7)) / 2, y: 0)\\n\\n                }.frame(height: 400)\\n            }\\n        }\\n    }\\n\\n}\\n\")), mdx(\"p\", null, \"Take a look at this next example...We put a list of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" containers inside a scrollview. Note that we need to give each of them a fixed height for it to be displayed.\"), mdx(\"p\", null, \"When you scroll, you will see that only the global \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"minY\"), \" changes. There are 2 reasons for that:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"The default scroll \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"axis\"), \" is \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"vertical\"), \", so only y values are changing.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"The global coordinates are relative to the device's screen which means they reflect the origin position in the screen's rectangle.\")), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613503558/Overview%20blog%20posts/GeometryReader/uieovnh1q2vgps43kfqm.gif\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613503558/Overview%20blog%20posts/GeometryReader/uieovnh1q2vgps43kfqm.gif\"\n  }))), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    // highlight-start\\n    var screenHeight = UIScreen.main.bounds.height\\n    var screenWidth = UIScreen.main.bounds.width\\n    // highlight-end\\n\\n    var body: some View {\\n        ScrollView {\\n            ForEach(0 ..< 15) { item in\\n                GeometryReader { geometry in\\n                    // highlight-start\\n                    createImage(geometry: geometry)\\n                    // highlight-end\\n                }.frame(height: 700)\\n            }\\n        }\\n    }\\n\\n    // highlight-start\\n    private func createImage(geometry: GeometryProxy) -> some View {\\n\\n    }\\n    // highlight-end\\n}\\n\")), mdx(\"p\", null, \"For the final demo, we need the entire device screen height and width. We then replace the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Text\"), \" view with the call to that \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createImage\"), \" function created a little bit down.\"), mdx(\"p\", null, \"Now let's do the remaining work in that function.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"// $$liquidcoderFilename-ContentView\\n\\nimport SwiftUI\\n\\nstruct ContentView1: View {\\n\\n    var screenHeight = UIScreen.main.bounds.height\\n    var screenWidth = UIScreen.main.bounds.width\\n\\n    var body: some View {\\n        ScrollView {\\n            ForEach(0 ..< 15) { item in\\n                GeometryReader { geometry in\\n                    createImage(geometry: geometry)\\n                }.frame(height: 700)\\n            }\\n        }\\n    }\\n\\n    private func createImage(geometry: GeometryProxy) -> some View {\\n\\n        // highlight-start\\n        let height = geometry.size.height\\n        let minY = geometry.frame(in: .global).minY\\n\\n        let scrolledInterval = max(0, min(minY, screenHeight))\\n        let scrolledPercent = scrolledInterval / screenHeight\\n\\n        return Image(\\\"image\\\")\\n            .resizable()\\n            .frame(width: screenWidth, height: height - (height * scrolledPercent) )\\n            .rotation3DEffect(\\n                Angle(degrees: 70 * Double(scrolledPercent)) ,\\n                axis: (x: 1.0, y: 0.0, z: 0.0),\\n                anchorZ: 0.0,\\n                perspective: -1.0\\n            ).scaleEffect(1.0 - scrolledPercent)\\n        // highlight-end\\n    }\\n}\\n\")), mdx(\"p\", null, \"The main component that makes the effect possible is the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"minY\"), \" from the frame which is the only dynamic variable in this case.\"), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613640167/Overview%20blog%20posts/GeometryReader/mgzz0e9oscdlfwdit7eb.gif\",\n    \"alt\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1613640167/Overview%20blog%20posts/GeometryReader/mgzz0e9oscdlfwdit7eb.gif\"\n  }))), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GeometryReader\"), \" is one of the most powerful features in swiftUI. One can create amazing effects with it, and sky is the only limit really.\"));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"Apple says: \"A container view that defines its content as a function of its own size and coordinate space. This view returns a flexible preferred size to its parent layout.\" In simple term,  GeometryReader  is a container that will fill the available space, unless given a fixed frame, and will…"}}}},"pageContext":{"slug":"geometryreader-overview"}},"staticQueryHashes":["1047155515","1278771865","2517639938","2517639938","2537039069","3452127246","3566879862","3891201089","439617394","670651827"]}