61. Примеры для MatchedGeometryEffect
Oleg991В этой статье покажу несколько вариантов настроек модификатора matchedGeometryEffect
с использованием одинаковой анимации linear(duration: 0.5)
. Этот модификатор определяет группу вьюшек с синхронизированной геометрией, используя идентификатор и неймспейс, которые мы предоставляем.
Дано
- Есть 2 фигуры: зеленый круг и черный прямоугольник
- При нажатии на кнопку "Сменить фигуру" нужно показать другую вьюху
- Под зеленым кругом и над черным прямоугольником есть спейсер фиксированной высоты (для наглядности разницы в анимациях)
Стартовый код:
struct MatchedGeometryEffectExample: View { @State private var showCircle = false var body: some View { ZStack { VStack(spacing: 4) { noEffectOption // без matchedGeometryEffect } Button("Сменить фигуру") { withAnimation(.linear(duration: 0.5)) { showCircle.toggle() } } .buttonStyle(.borderedProminent) } } /// Не использует `matchedGeometryEffect` @ViewBuilder private var noEffectOption: some View { if showCircle { greenCircle } else { blackRectangle } } private var greenCircle: some View { VStack(spacing: 0) { Circle() .fill(.green) .frame(width: 100, height: 100) spacerWithFrame } } private var blackRectangle: some View { VStack(spacing: 0) { spacerWithFrame Rectangle() .frame(width: 300, height: 50) } } private var spacerWithFrame: some View { Spacer().frame(height: 100) }
Как видим на гифке, при нажатии на кнопку одна фигура исчезает, а другая появляется, при этом обе фигуры сохраняют свои положения (т.к. в обоих случаях есть фиксированный спейсер).
Дефолтный matchedGeometryEffect
Добавим matchedGeometryEffect
с дефолтными настройками. Для этого нам понадобится задать идентификатор и namespace
для анимации (код для фигур прежний):
struct MatchedGeometryEffectExample: View { @State private var showCircle = false @Namespace private var defaultAnimation // <- добавили private let defaultAnimationId = "defaultAnimation" // <- добавили var body: some View { ZStack { VStack(spacing: 4) { defaultOption // matchedGeometryEffect без настроек } Button("Сменить фигуру") { withAnimation(.linear(duration: 0.5)) { showCircle.toggle() } } .buttonStyle(.borderedProminent) } } /// Использует `matchedGeometryEffect`, параметры по умолчанию @ViewBuilder private var defaultOption: some View { if showCircle { greenCircle .matchedGeometryEffect( id: defaultAnimationId, in: defaultAnimation ) } else { blackRectangle .matchedGeometryEffect( id: defaultAnimationId, in: defaultAnimation ) } } }
Теперь при анимации вьюхи двигаются, меняя свое положение, что на мой взгляд выглядит интереснее, чем простое изменение прозрачности как в первом случае.
Настраиваем все кроме источника
В этом примере настроим два дополнительных параметра в модификаторе: properties
и anchor
:
@ViewBuilder private var customAnchorAndPropertiesOption: some View { if showCircle { greenCircle .matchedGeometryEffect( id: animationTwoId, in: animationTwo, properties: .position, // <- добавили anchor: .trailing // <- добавили ) } else { blackRectangle .matchedGeometryEffect( id: animationTwoId, in: animationTwo, anchor: .leading // <- добавили ) } }
В очередной раз видим новое поведение, осталось 2 сценария.
Настраиваем источником вычислений круг
@ViewBuilder private var customOptionCircleIsSource: some View { if showCircle { greenCircle .matchedGeometryEffect( id: animationFourId, in: animationFour ) } else { blackRectangle .matchedGeometryEffect( id: animationFourId, in: animationFour, isSource: false // <- добавили, по умолчанию тут true ) } }
Видим, что при возврате к исходному состоянию круг не движется, а просто появляется как было в самом первом примере без использования matchedGeometryEffect
.
Настраиваем источником вычислений прямоугольник
@ViewBuilder private var customOptionRectangleIsSource: some View { if showCircle { greenCircle .matchedGeometryEffect( id: animationThreeId, in: animationThree, isSource: false // <- добавили, по умолчанию тут true ) } else { blackRectangle .matchedGeometryEffect( id: animationThreeId, in: animationThree ) } }
Видим, что при возврате к исходному состоянию прямоугольник не движется, а просто появляется как было в самом первом примере без использования matchedGeometryEffect
.
Заключение
С использованием matchedGeometryEffect
можно сделать много интересных анимаций - экспериментируйте и предлагайте дизайнерам 🙂
Код для этой статьи можно посмотреть тут, а другие статьи - тут.