SwiftUI实现带动画的L形自定义菜单及导航栏适配问题问询
SwiftUI实现带动画的L形自定义菜单及导航栏适配问题问询
大家好!我觉得苹果系统自带的菜单和运动应用都挺酷的,但我想做个更有新意的自定义菜单,目前已经写出了一段代码,实现了一个带展开动画的下拉菜单效果:
完整代码
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形的带动画菜单,参考样式如下:
另外还有个小问题:我尝试把这个自定义菜单视图添加到导航栏的按钮项中,但出现了不少bug,有没有大佬能给点实现思路或者适配建议呀?
(抱歉我的英语语法不太好,希望大家能理解我的需求 😊)
备注:内容来源于stack exchange,提问作者Antonio A. Chavez
相关产品推荐
相关产品推荐

