Переход с matchedGeometryEffect корректно работает только в одном направлении.
Попытка сделать сегментированную анимацию управления с изменением цвета опций. В одном направлении все работает хорошо, а в другом фон выше контента. Я хочу сделать это без GeometryReader.
Анимация хорошо работает в одном направлении: https://stackru.com/images/6c5397e3288ffe90042f5e3c8951bd470a354e4b.gif
Но вот как это работает в другом направлении: https://stackru.com/images/9800e1cf288892f268845f1c65808c0ddf19c6e5.gif
Код подборщика:
struct CustomPicker<Option: CustomPickerOption>: View {
// MARK: - Properties
@Binding var selection: Option
let options: [Option]
@Namespace private var namespaceID
private let buttonBackgroundID: String = "buttonOverlayID"
private let buttonOverlayID: String = "buttonOverlayID"
// MARK: - UI
var body: some View {
HStack(spacing: 0) {
ForEach(options) { option in
Segment(
title: option.title,
isSelected: selection == option,
backgroundID: buttonBackgroundID,
overlayID: buttonOverlayID,
namespaceID: namespaceID,
action: { selection = option }
)
}
}
.padding(4)
.background(Color.blue)
.clipShape(Capsule())
}
}
Код сегмента:
private struct Segment: View {
// MARK: - Properties
let title: String
let isSelected: Bool
let backgroundID: String
let overlayID: String
let namespaceID: Namespace.ID
let action: () -> Void
@State private var isPressed: Bool = false
// MARK: - UI
var body: some View {
Button(action: action) {
titleView
.blendMode(.difference)
.overlay(
titleView
.blendMode(.hue)
)
.overlay(
titleView
.foregroundColor(.black)
.blendMode(.overlay)
)
.background {
if isSelected {
background
.matchedGeometryEffect(id: backgroundID, in: namespaceID)
.transition(.offset())
}
}
}
.buttonStyle(.customHighlighted(isPressed: $isPressed))
}
private var background: some View {
Color.white
.clipShape(Capsule())
}
private var titleView: some View {
Text(title)
.font(\.semibold)
.foregroundColor(.white)
.padding(.horizontal, 12)
.padding(.vertical, 10)
}
}
Я пытался заменить.transition(.offset)
и используйте другие переходы, добавьте.frame(maxWidth: .infinity, maxHeight: .infinity)
, но ничего не работает. Есть ли другие решения этой проблемы?.animation(.default, value: isSelected)
добавляет эффект затухания, так что это не лучшее решение.
Обновлять:zIndex(selection == option ? 1 : 0)
помогает нормализовать переход. Честно говоря, я не понимаю, почему. Если можете, пожалуйста, объясните этот странный хак.