SwiftUI передает значение из считывателя геометрии в функцию - PullRequest
1 голос
/ 03 марта 2020

У меня есть представление, которое использует Geometry Reader для вычисления размера области изображения:

GeometryReader { metrics in
    ZStack{
        self.image
           .resizable()
           .frame(width:  (metrics.size.height - 10) * 0.561403509 , height: metrics.size.height - 10, alignment: .top)
           .clipped()
    }
}

Но у меня есть функция, в которой я хочу использовать высоту и ширину кадра, вычисленные GeometryReader в Чтобы обрезать изображение.

У меня есть отдельная функция, которая обрезает изображение при нажатии кнопки:

 DownloadImageButton(prepareImagefunction: { self.prepareImage() })

, которая затем вызывает функцию prepareImage:

func prepareImage( ) {
 // In order for image cropping to work, we need the equivalent of view.bounds in order to adjust the crop so that it correctly measures the crop area. We need metrics.width and metrics.height 
 var adjustmentScaleForDisplaySize = targetSize.width / metrics.width

Обратите внимание, что GeometryReader является дочерним элементом родительского представления, где вызывается prepareImage. Поэтому в идеале дочерний элемент должен сохранять значения метрик в EnvironmentObject или Binding к родительскому элементу.

Ответы [ 2 ]

3 голосов
/ 04 марта 2020

Есть ли способ передать значение, вычисленное GeometryReader, в функцию?

Да, вы можете сделать это. Переменная metrics представляет собой GeometryProxy, поэтому сигнатура функции должна быть такой, как в следующем примере

private func resizedImage(for metrics: GeometryProxy) -> some View {
    self.image
       .resizable()
       .frame(width:  (metrics.size.height - 10) * 0.561403509 , height: metrics.size.height - 10, alignment: .top)
       .clipped()
}

, поэтому ваше использование

GeometryReader { metrics in
    ZStack{
       self.resizedImage(for: metrics)
    }
}

Обновление: для измененный запрос

Предполагая, что в дочернем виде привязка имеет вид

@Binding var cropSize: CGSize

вышеупомянутая функция может быть изменена следующим образом

private func resizedImage(for metrics: GeometryProxy) -> some View {
    let size = CGSize(width: (metrics.size.height - 10) * 0.561403509, 
                           height: metrics.size.height - 10)
    self.cropSize = size
    return self.image
       .resizable()
       .frame(width: size.width, height: size.height, alignment: .top)
       .clipped()
}
0 голосов
/ 05 марта 2020

Так как на самом деле мне нужен был ТОЛЬКО размер кадрирования и необязательно возвращалось изображение, я сделал следующее, что также помогло избежать ошибки, которая может возникнуть в принятом ответе:

[SwiftUI] Modifying state during view update, this will cause undefined behavior.

Я добавил вызов функции .onAppear, который помогает избежать вышеуказанной ошибки, а затем правильно передает измерение обрезки родительскому элементу:

GeometryReader { metrics in
  ZStack{
   self.image
   .resizable()
   .frame(width:  (metrics.size.height - 10) * 0.561403509 , height: metrics.size.height - 10, alignment: .top)
   .clipped()
  }.onAppear{
    self.saveCropSize(for: metrics)
  }....

private func saveCropSize(for metrics: GeometryProxy){
    let size = CGSize(width: (metrics.size.height - 10) * 0.561403509, 
                           height: metrics.size.height - 10)
    self.cropSize = size
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...