SwiftUI如何实现顶部圆角底部外凸曲线的自定义TabBar?
实现SwiftUI自定义反向圆角TabBar

我想要在SwiftUI中实现如图所示的自定义TabBar形状:顶部左右角为常规圆角,底部左右角为反向曲线(向外凸起的独特造型)。
我尝试过使用clipShape搭配简单的RoundedRectangle,但它无法实现底部角落的反向曲线效果。请问如何创建符合图中样式的SwiftUI自定义Shape?
我的尝试代码:
// // CustomTabBar.swift // skill // // Created by Chetan Patil on 06/12/24. // import SwiftUI struct CustomTabBar: View { @State private var selectedTab: Tab = .favourites // 跟踪选中标签的状态 enum Tab { case favourites, accounts, payments, deposits } var body: some View { VStack(spacing: 0) { // 标签栏内容 // 自定义Tab Bar HStack { tabItem(title: "Favourites", isSelected: selectedTab == .favourites) { selectedTab = .favourites } tabItem(title: "Accounts", isSelected: selectedTab == .accounts) { selectedTab = .accounts } tabItem(title: "Payments", isSelected: selectedTab == .payments) { selectedTab = .payments } tabItem(title: "Deposits", isSelected: selectedTab == .deposits) { selectedTab = .deposits } } .background(Color(red: 0/255, green: 64/255, blue: 143/255)) // 内容区域 TabView(selection: $selectedTab) { FavouritesView() .tag(Tab.favourites) AccountsView() .tag(Tab.accounts) PaymentsView() .tag(Tab.payments) DepositsView() .tag(Tab.deposits) } .frame(maxWidth: .infinity, maxHeight: 400) } .ignoresSafeArea(edges: .bottom) // 让TabBar延伸到底部安全区外 } // 单个标签项视图 private func tabItem(title: String, isSelected: Bool, action: @escaping () -> Void) -> some View { Button(action: action) { Text(title) .font(.system(size: 14, weight: isSelected ? .bold : .regular)) .foregroundColor(isSelected ? .black : .gray) .padding(.vertical, 12) .frame(maxWidth: .infinity) } .background(isSelected ? Color.white : Color.clear) // 高亮选中的标签 .clipShape( .rect( topLeadingRadius: 10, bottomLeadingRadius: -10, bottomTrailingRadius: -10, topTrailingRadius: 10 ) ) } } // 各标签页的示例视图 struct FavouritesView: View { var body: some View { Text("收藏页") .frame(maxWidth: .infinity, maxHeight: 400) .background(Color.white) } } struct AccountsView: View { var body: some View { Text("账户页") .frame(maxWidth: .infinity, maxHeight: 400) .background(Color.white) } } struct PaymentsView: View { var body: some View { Text("支付页") .frame(maxWidth: .infinity, maxHeight: 400) .background(Color.white) } } struct DepositsView: View { var body: some View { Text("存款页") .frame(maxWidth: .infinity, maxHeight: 400) .background(Color.white) } } #Preview { CustomTabBar() }
解决方案:自定义Shape实现反向圆角
要实现底部向外凸起的反向曲线,需要自定义一个遵循Shape协议的结构体,手动绘制路径:
struct CustomTabBarShape: Shape { let cornerRadius: CGFloat func path(in rect: CGRect) -> Path { var path = Path() // 绘制顶部左圆角 path.move(to: CGPoint(x: rect.minX + cornerRadius, y: rect.minY)) path.addArc(center: CGPoint(x: rect.minX + cornerRadius, y: rect.minY + cornerRadius), radius: cornerRadius, startAngle: .degrees(270), endAngle: .degrees(180), clockwise: false) // 绘制顶部右圆角 path.addLine(to: CGPoint(x: rect.maxX - cornerRadius, y: rect.minY)) path.addArc(center: CGPoint(x: rect.maxX - cornerRadius, y: rect.minY + cornerRadius), radius: cornerRadius, startAngle: .degrees(270), endAngle: .degrees(0), clockwise: false) // 绘制底部右反向圆角(向外凸) path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - cornerRadius)) path.addArc(center: CGPoint(x: rect.maxX - cornerRadius, y: rect.maxY - cornerRadius), radius: cornerRadius, startAngle: .degrees(0), endAngle: .degrees(90), clockwise: false) // 绘制底部左反向圆角(向外凸) path.addLine(to: CGPoint(x: rect.minX + cornerRadius, y: rect.maxY)) path.addArc(center: CGPoint(x: rect.minX + cornerRadius, y: rect.maxY - cornerRadius), radius: cornerRadius, startAngle: .degrees(90), endAngle: .degrees(180), clockwise: false) path.closeSubpath() return path } }
然后修改原代码中的TabBar背景部分,应用这个自定义Shape:
HStack { // 原tabItem代码保持不变 } .background(Color(red: 0/255, green: 64/255, blue: 143/255)) .clipShape(CustomTabBarShape(cornerRadius: 10)) // 添加这一行应用自定义形状
如果需要调整反向曲线的弧度,只需要修改cornerRadius参数即可。
内容的提问来源于stack exchange,提问作者Chetan patil
相关产品推荐
相关产品推荐

