SwiftUI 2 matchedGeometryЭффект: порядок модификаторов

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Я ломал голову над созданием желаемого matchedGeometryEffect с помощью SwiftUI 2. Во время этого процесса обучения что-то прошло мой путь, который я действительно не могу объяснить. Я покажу пример.

Я пытаюсь создать переход Список -> Детали с эффектом, обычно называемым эффектом «Героя». Изображение профиля в представлении списка переходит к большому баннеру в подробном представлении.

Для достижения этой цели я создал два KFImages (KF = Kingfisher, пакет, который я использую для удобной загрузки и кэширования изображений) с несколькими модификаторами:

Просмотр списка:

 if !isProductDetailViewPresented {
   KFImage(store.results.first?.images?.first?.url)
      .resizable()
      .cornerRadius(30)
      .scaledToFill()
      .matchedGeometryEffect(id: "image.testprod", in: animationNamespace!, anchor: .center, isSource: !isProductDetailViewPresented)
      .animation(.easeInOut(duration: 0.3))
      .frame(width: 60, height: 60, alignment: .center)
      .zIndex(999)
}
  

Подробный просмотр:

 if isProductDetailViewPresented {

...

    KFImage(product?.images?.first?.url)
        .resizable()
        .scaledToFill()
        .cornerRadius(30)
        .matchedGeometryEffect(id: "image.testprod", in: animationNamespace!, anchor: .center, isSource: isProductDetailViewPresented)
        .frame(height: 300)
        .animation(.easeInOut(duration: 0.3))

...

}
  

… это почти сработало; каким-то образом мое изображение не будет ограничиваться .frame(width: 60, height: 60) . Вместо этого он растягивается, чтобы поместить изображение в представление, делая ширину больше 60. Высота остается на уровне 60.

Чтобы исправить это, я подумал; возможно, этот .frame() модификатор следует поместить перед .matchedGeometryEffect() модификатором. Но когда я это делаю, меняется только положение двух изображений; не размер. Это заставляет меня думать, что .matchedGeometryEffect() модификаторы считают фреймы «фиксированными» для размещения .frame() модификаторов перед .matchedGeometryEffect() модификаторами.

Это странно, так как несколько примеров в Интернете показывают код, в котором .frame() вызывается раньше .matchedGeometryEffect() , например , здесь (поиск .matchedGeometryEffect() , их всего 2) и здесь (раздел «Следовать за последователем»).

Два вопроса:

  1. Почему мой работает только тогда, когда я звоню .frame() после .matchedGeometryEffect() , в то время как онлайн-источники делают обратное?

  2. Как .matchedGeometryEffect() обрабатывать порядок модификаторов? Что я должен принять во внимание?

Честно говоря, я довольно плохо разбираюсь в этом API. Я надеюсь, что вы, ребята, сможете прояснить ситуацию для меня. 🙂

Комментарии:

1. У вас когда-нибудь был этот уточненный Jaap? 🙂 Возможно, это я задал ваш вопрос сегодня вечером.