#swiftui
#swiftui
Вопрос:
Цель: принудительно поместить изображение кнопки за другим изображением, чтобы при появлении / исчезновении других кнопок они не отображались на экране до тех пор, пока не выйдут за край верхнего изображения. Пример, но, похоже, это работает только тогда, когда кнопки исчезают.
Текущее: кнопки исчезают и накладываются на верхнюю кнопку. Пример.
Попытка: я отрегулировал непрозрачность и попытался использовать ZStack, но ни один из подходов не был успешным.
Код:
struct buttonReveal : View {
@State var isShowing = false
var body: some View {
HStack{
ZStack{
Circle()
.foregroundColor(.white)
.frame(width: 100, height: 100)
Button(action: {
withAnimation(.linear(duration: 0.5)) { self.isShowing.toggle() }
}, label: {
ZStack {
Circle()
.foregroundColor(.white)
.frame(width: 100, height: 100)
Image(systemName: "chevron.forward.circle")
.buttonModifier()
}
.rotationEffect(Angle(degrees: isShowing ? -180 : 0))
.animation(.spring())
})
}
if isShowing {
Button(action: {
isShowing.toggle()
}, label: {
Image(systemName: "trash.circle")
.buttonModifier()
})
.transition(.moveAndFade(edge: .leading, offsetX: 0, offsetY: 0))
.animation(.spring())
Button(action: {
isShowing.toggle()
}, label: {
Image(systemName: "gear")
.buttonModifier()
})
.transition(.moveAndFade(edge: .leading, offsetX: -150, offsetY: 0))
.animation(.spring())
} else {
Spacer()
}
}
}
}
extension AnyTransition {
static func moveAndFade(edge: Edge, offsetX: CGFloat, offsetY: CGFloat) -> AnyTransition {
AnyTransition.move(edge: edge).combined(with: .opacity).combined(with: offset(x: offsetX, y: offsetY))
}
}
extension Image {
func buttonModifier() -> some View {
self
.resizable()
.frame(width: 100, height: 100)
.foregroundColor(.primary)
.padding()
}
}
Ответ №1:
Не уверен, что это лучшая практика, она не идеально выравнивается и нуждается в некоторой очистке, но, возможно, поможет вам двигаться в правильном направлении..
по сути, я создал вторичный HStack, который находится под основным, в отличие от двух, использующих один и тот же
(может быть, кто-нибудь может дать рекомендации по улучшению практики)
struct buttonReveal : View {
@State var isShowing = false
var body: some View {
ZStack {
HStack {
Spacer().frame(width: 100, height: 100)
if isShowing {
Button(action: {
isShowing.toggle()
}, label: {
Image(systemName: "trash.circle")
.buttonModifier()
})
.transition(.moveAndFade(edge: .leading, offsetX: 0, offsetY: 0))
.animation(.spring())
Button(action: {
isShowing.toggle()
}, label: {
Image(systemName: "gear")
.buttonModifier()
})
.transition(.moveAndFade(edge: .leading, offsetX: -150, offsetY: 0))
.animation(.spring())
}
}
HStack {
ZStack {
Circle()
.foregroundColor(.white)
.frame(width: 100, height: 100)
Button(action: {
withAnimation(.linear(duration: 0.5)) { self.isShowing.toggle() }
}, label: {
ZStack {
Circle()
.foregroundColor(.white)
.frame(width: 100, height: 100)
Image(systemName: "chevron.forward.circle")
.buttonModifier()
}
.rotationEffect(Angle(degrees: isShowing ? -180 : 0))
.animation(.spring())
})
}
Spacer()
}
}
}
}
Ответ №2:
Это работает для вас? Вместо того, чтобы рисовать кнопки на экране при отображении, я просто включил их уже на экране в ZStack, за верхней кнопкой.
struct ButtonReveal: View {
@State var isShowing = false
var body: some View {
ZStack {
Image(systemName: "gear")
.buttonModifier()
.offset(x: isShowing ? 300 : 0)
Image(systemName: "trash.circle")
.buttonModifier()
.offset(x: isShowing ? 150 : 0)
Image(systemName: "chevron.forward.circle")
.buttonModifier()
.rotationEffect(Angle(degrees: isShowing ? -180 : 0))
}
.animation(.spring())
.onTapGesture {
isShowing.toggle()
}
}
}
struct ButtonReveal_Previews: PreviewProvider {
static var previews: some View {
ButtonReveal()
.frame(maxWidth: .infinity, alignment: .leading)
}
}
extension Image {
func buttonModifier() -> some View {
self
.resizable()
.frame(width: 100, height: 100)
.foregroundColor(.primary)
.padding()
.background(
Circle()
.fill(Color.white)
)
}
}