Что такое Geometry Reader в SwiftUI?

Я изучаю SwiftUI. И я натыкаюсь на "GeometryReader". И я хочу знать, почему и когда его использовать?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
54
0
29 354
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Обновлено

Поскольку я опубликовал ответ, я также написал статью о том, как работает GeometryReader. Проверьте это для более подробного объяснения: https://swiftui-lab.com/geometryreader-to-the-rescue/


GeometryReader — это представление, которое дает вам доступ к размеру и положению его родителя. Например:

struct MyView: View {
    var body: some View {
        GeometryReader { geometry in
           // Here goes your view content,
           // and you can use the geometry variable
           // which contains geometry.size of the parent
           // You also have function to get the bounds
           // of the parent: geometry.frame(in: .global)
        }
    }
}

Я обычно комбинирую его с .background(), чтобы получить границы другого вида. Например, для представления «Текст» трудно заранее предсказать, насколько большим оно будет. Когда мне нужна эта информация, я использую этот трюк:

Сначала я определил представление GeometryGetter:

struct GeometryGetter: View {
    @Binding var rect: CGRect
    
    var body: some View {
        return GeometryReader { geometry in
            self.makeView(geometry: geometry)
        }
    }
    
    func makeView(geometry: GeometryProxy) -> some View {
        DispatchQueue.main.async {
            self.rect = geometry.frame(in: .global)
        }

        return Rectangle().fill(Color.clear)
    }
}

Затем, чтобы получить границы текстового представления (или любого другого представления):

struct MyView: View {
    @State private var rect: CGRect = CGRect()

    var body: some View {
        Text("some text").background(GeometryGetter($rect))

        // You can then use rect in other places of your view:
        Rectangle().frame(width: 100, height: rect.height)
    }
}

Для некоторых случаев использования я опубликовал несколько ответов на другие вопросы, связанные с использованием GeometryReader. Проверь их:

Переместите текстовые поля, чтобы они не были скрыты клавиатурой: https://stackoverflow.com/a/56721268/7786555

Как сделать представление размером с другое представление в SwiftUI: https://stackoverflow.com/a/56661706/7786555

Примечание

В GeometryGetter я добавил DispatchQueue.main.async {} для установки прямоугольника. В некоторых случаях это может привести к предупреждению во время выполнения: Изменение состояния во время обновления представления.

Обновлен ответ, чтобы включить некоторые варианты использования.

kontiki 24.06.2019 06:40

Поскольку я опубликовал ответ, я добавил ссылку на статью, которую я написал о GeometryReader. Это расширяет ответ дальше. Ваше здоровье.

kontiki 01.07.2019 17:34

Можете ли вы помочь нам здесь stackoverflow.com/questions/57243677/… понять, почему GeometryReader в принятом ответе нуждается в модификаторе layoutPriority, чтобы получить результат? Спасибо.

matteopuc 30.07.2019 01:10

Этот получатель геометрии очень полезен. Спасибо за публикацию.

テッド 27.02.2020 12:25

Очень полезный способ использования программы чтения геометрии, но я думаю, что асинхронный вызов фрейма (in:) не является хорошей идеей для динамического контента (например, просмотр внутреннего списка), это приведет к сбою, обходным путем будет синхронная выборка фрейма а затем отправить его асинхронно

Aleyam 22.05.2020 19:01

@Aleyam, у вас есть пример кода, и если да, то готовы ли вы создать его в качестве ответа? Спасибо.

iPadawan 13.08.2020 22:25

У меня вылетает self.rect = geometry.frame(in: .global) при смене вкладок. По-видимому, удаление асинхронного вызова заставляет его снова работать.

mcatach 14.08.2020 07:05

Что называется Reader в SwiftUI?

В дополнение к ответу kontiki, Readers - это контейнерные представления, которые определяют свое содержимое как функцию. Таким образом, у них может быть некоторый доступ и способности к их parent. Это общие структуры, если вы присмотритесь поближе, и в SwiftUI 2.0 теперь доступны 2 средства чтения:

Note that it's just a convention, they're not conforming special protocol more of the View protocl.

GeometryReader

struct GeometryReader<Content: View> : View

Это представление контейнера, которое определяет свое содержимое как функцию собственного размера и координатного пространства. Таким образом, вы можете обнаруживать изменения кадра и положения, а также текущее состояние любого представления в GeometryReader. Одно из популярных применений этого считывателя, когда вам нужны отдельные представления в отдельных стеках, имеют одинаковые (или относительные) размеры.


ScrollViewReader

struct ScrollViewReader<Content: View> : View

Это представление, дочерний элемент которого определяется как функция ScrollViewProxy, нацеленная на прокручиваемые представления внутри дочернего элемента. Таким образом, у вас может быть некоторый доступ к прокрутке, такой как прокрутка к определенному элементу в списке или что-то подобное.

To minimalizing the duplication, I didn't post examples, you can check the link for more information if you want

GeometryReader - это то, что распознает геометрию родительского представления, что означает, что когда вы создаете представление в геометрии, вы получаете размер своего родительского представления.

Другие вопросы по теме