




Поскольку я опубликовал ответ, я также написал статью о том, как работает 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 {} для установки прямоугольника. В некоторых случаях это может привести к предупреждению во время выполнения: Изменение состояния во время обновления представления.
Поскольку я опубликовал ответ, я добавил ссылку на статью, которую я написал о GeometryReader. Это расширяет ответ дальше. Ваше здоровье.
Можете ли вы помочь нам здесь stackoverflow.com/questions/57243677/… понять, почему GeometryReader в принятом ответе нуждается в модификаторе layoutPriority, чтобы получить результат? Спасибо.
Этот получатель геометрии очень полезен. Спасибо за публикацию.
Очень полезный способ использования программы чтения геометрии, но я думаю, что асинхронный вызов фрейма (in:) не является хорошей идеей для динамического контента (например, просмотр внутреннего списка), это приведет к сбою, обходным путем будет синхронная выборка фрейма а затем отправить его асинхронно
@Aleyam, у вас есть пример кода, и если да, то готовы ли вы создать его в качестве ответа? Спасибо.
У меня вылетает self.rect = geometry.frame(in: .global) при смене вкладок. По-видимому, удаление асинхронного вызова заставляет его снова работать.
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.
struct GeometryReader<Content: View> : View
Это представление контейнера, которое определяет свое содержимое как функцию собственного размера и координатного пространства. Таким образом, вы можете обнаруживать изменения кадра и положения, а также текущее состояние любого представления в GeometryReader. Одно из популярных применений этого считывателя, когда вам нужны отдельные представления в отдельных стеках, имеют одинаковые (или относительные) размеры.
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 - это то, что распознает геометрию родительского представления, что означает, что когда вы создаете представление в геометрии, вы получаете размер своего родительского представления.
Обновлен ответ, чтобы включить некоторые варианты использования.