Anonymous
Как сделать меню просмотра L-образной формы с анимацией? (Идея пользовательского меню/SwiftUI)
Сообщение
Anonymous » 09 мар 2026, 00:10
Меню Apple и приложение Sport — это круто, но я хочу, чтобы моя идея была круче других. Пытаюсь сделать новое!
Вот полный код:
Код: Выделить всё
import SwiftUI
struct ContentView: View {
@State private var isExpanded = false
@State private var pillWidth: CGFloat = 0
let height: CGFloat = 40
var body: some View {
ZStack(alignment: .topLeading) {
VStack(alignment: .leading, spacing: 3) {
// PILL
HStack(spacing: 3) {
Button {
withAnimation(.spring(response: 0.35, dampingFraction: 0.85)) {
isExpanded.toggle()
}
} label: {
HStack(spacing: 3) {
Image(systemName: "person.crop.square.on.square.angled.fill")
Text("1 Sign")
.fontWeight(.regular)
}
.padding(.horizontal, 16)
.frame(height: height)
.background(
Color.gray.opacity(0.2)
.clipShape(
CustomCorners(
tl: height/2,
tr: 2,
bl: height/2,
br: 2
)
)
)
}
Image(systemName: "chevron.right")
.rotationEffect(.degrees(isExpanded ? 90 : 0))
.animation(.easeInOut(duration: 0.2), value: isExpanded)
.foregroundColor(.gray)
.frame(width: height, height: height)
.background(
Color.gray.opacity(0.2)
.clipShape(
CustomCorners(
tl: 2,
tr: height/2,
bl: 2,
br: height/2
)
)
)
}
.background(
GeometryReader { geo in
Color.clear
.onAppear {
pillWidth = geo.size.width
}
}
)
// DROPDOWN
if isExpanded {
VStack(alignment: .leading, spacing: 15) {
row("2 Sign")
row("3 Sign")
row("4 Sign")
}
.padding(.vertical, 17)
.frame(width: pillWidth)
.background(
RoundedRectangle(cornerRadius: 28)
.fill(Color.gray.opacity(0.2))
)
.scaleEffect(y: isExpanded ? 1 : 0, anchor: .top)
.opacity(isExpanded ? 1 : 0)
.offset(y: isExpanded ? 0 : -10)
.animation(.spring(response: 0.35, dampingFraction: 0.85), value: isExpanded)
}
}
}
.padding(40)
}
}
func row(_ title: String) -> some View {
HStack {
Text(title)
Spacer()
Image(systemName: "chevron.right")
}
.padding(.horizontal, 16)
.frame(height: 28)
}
struct CustomCorners: Shape {
var tl: CGFloat = 0
var tr: CGFloat = 0
var bl: CGFloat = 0
var br: CGFloat = 0
func path(in rect: CGRect) -> Path {
let path = UIBezierPath()
path.move(to: CGPoint(x: rect.minX + tl, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX - tr, y: rect.minY))
path.addArc(withCenter: CGPoint(x: rect.maxX - tr, y: rect.minY + tr),
radius: tr, startAngle: .pi * 1.5, endAngle: 0, clockwise: true)
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - br))
path.addArc(withCenter: CGPoint(x: rect.maxX - br, y: rect.maxY - br),
radius: br, startAngle: 0, endAngle: .pi * 0.5, clockwise: true)
path.addLine(to: CGPoint(x: rect.minX + bl, y: rect.maxY))
path.addArc(withCenter: CGPoint(x: rect.minX + bl, y: rect.maxY - bl),
radius: bl, startAngle: .pi * 0.5, endAngle: .pi, clockwise: true)
path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + tl))
path.addArc(withCenter: CGPoint(x: rect.minX + tl, y: rect.minY + tl),
radius: tl, startAngle: .pi, endAngle: .pi * 1.5, clockwise: true)
return Path(path.cgPath)
}
}
#Preview {
ContentView()
}
Результат:
Кстати: я создаю меню для своего приложения SignDict. поэтому мне нужна идея... сделать L-образную форму с анимацией... есть идеи?
ПРИМЕЧАНИЕ. Я пытаюсь поместить это пользовательское представление меню в кнопку элемента панели навигации, при добавлении к нему тоже возникла ошибка, и извините, если моя английская грамматика ужасна!
Подробнее здесь:
https://stackoverflow.com/questions/799 ... ea-swiftui
1773004233
Anonymous
Меню Apple и приложение Sport — это круто, но я хочу, чтобы моя идея была круче других. Пытаюсь сделать новое! Вот полный код: [code]import SwiftUI struct ContentView: View { @State private var isExpanded = false @State private var pillWidth: CGFloat = 0 let height: CGFloat = 40 var body: some View { ZStack(alignment: .topLeading) { VStack(alignment: .leading, spacing: 3) { // PILL HStack(spacing: 3) { Button { withAnimation(.spring(response: 0.35, dampingFraction: 0.85)) { isExpanded.toggle() } } label: { HStack(spacing: 3) { Image(systemName: "person.crop.square.on.square.angled.fill") Text("1 Sign") .fontWeight(.regular) } .padding(.horizontal, 16) .frame(height: height) .background( Color.gray.opacity(0.2) .clipShape( CustomCorners( tl: height/2, tr: 2, bl: height/2, br: 2 ) ) ) } Image(systemName: "chevron.right") .rotationEffect(.degrees(isExpanded ? 90 : 0)) .animation(.easeInOut(duration: 0.2), value: isExpanded) .foregroundColor(.gray) .frame(width: height, height: height) .background( Color.gray.opacity(0.2) .clipShape( CustomCorners( tl: 2, tr: height/2, bl: 2, br: height/2 ) ) ) } .background( GeometryReader { geo in Color.clear .onAppear { pillWidth = geo.size.width } } ) // DROPDOWN if isExpanded { VStack(alignment: .leading, spacing: 15) { row("2 Sign") row("3 Sign") row("4 Sign") } .padding(.vertical, 17) .frame(width: pillWidth) .background( RoundedRectangle(cornerRadius: 28) .fill(Color.gray.opacity(0.2)) ) .scaleEffect(y: isExpanded ? 1 : 0, anchor: .top) .opacity(isExpanded ? 1 : 0) .offset(y: isExpanded ? 0 : -10) .animation(.spring(response: 0.35, dampingFraction: 0.85), value: isExpanded) } } } .padding(40) } } func row(_ title: String) -> some View { HStack { Text(title) Spacer() Image(systemName: "chevron.right") } .padding(.horizontal, 16) .frame(height: 28) } struct CustomCorners: Shape { var tl: CGFloat = 0 var tr: CGFloat = 0 var bl: CGFloat = 0 var br: CGFloat = 0 func path(in rect: CGRect) -> Path { let path = UIBezierPath() path.move(to: CGPoint(x: rect.minX + tl, y: rect.minY)) path.addLine(to: CGPoint(x: rect.maxX - tr, y: rect.minY)) path.addArc(withCenter: CGPoint(x: rect.maxX - tr, y: rect.minY + tr), radius: tr, startAngle: .pi * 1.5, endAngle: 0, clockwise: true) path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - br)) path.addArc(withCenter: CGPoint(x: rect.maxX - br, y: rect.maxY - br), radius: br, startAngle: 0, endAngle: .pi * 0.5, clockwise: true) path.addLine(to: CGPoint(x: rect.minX + bl, y: rect.maxY)) path.addArc(withCenter: CGPoint(x: rect.minX + bl, y: rect.maxY - bl), radius: bl, startAngle: .pi * 0.5, endAngle: .pi, clockwise: true) path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + tl)) path.addArc(withCenter: CGPoint(x: rect.minX + tl, y: rect.minY + tl), radius: tl, startAngle: .pi, endAngle: .pi * 1.5, clockwise: true) return Path(path.cgPath) } } #Preview { ContentView() } [/code] Результат: [img]https://i.sstatic.net/f4UJ176t.png[/img] Кстати: я создаю меню для своего приложения SignDict. поэтому мне нужна идея... сделать L-образную форму с анимацией... есть идеи? [img]https://i.sstatic.net/GPNrr9yQ.png[/img] ПРИМЕЧАНИЕ. Я пытаюсь поместить это пользовательское представление меню в кнопку элемента панели навигации, при добавлении к нему тоже возникла ошибка, и извините, если моя английская грамматика ужасна! Подробнее здесь: [url]https://stackoverflow.com/questions/79903462/how-to-make-a-l-shape-view-menu-with-animation-custom-menu-idea-swiftui[/url]