【发布时间】:2022-02-10 03:33:28
【问题描述】:
我正在开发自定义导航底部栏。我希望它是浮动的,但我意识到当我在其上添加 .padding() 时,其背景中的 .clipShape() 会失去对齐。
我已经编写了这个问题的简单版本。
没有填充的底部导航:
带内边距的底部导航:
主视图:
struct ContentView: View {
var body: some View {
VStack{
Spacer()
CustomBottomNav()
.padding() // <- THIS MAKE THE SHAPE TO LOSE ALIGN
}
}
自定义底部导航:
struct CustomBottomNav: View {
@State var selectedTab: Views = .HOME
@State private var xAxis: CGFloat = 0
@Namespace var animation
private let tabs: [Views] = [.SETTINGS, .RANKING, .HOME, .SALES, .SEARCHER]
private let iconSize: CGFloat = 25
private func isSelectedTab(_ tab: Views) -> Bool{
return selectedTab == selectedTab
}
var body: some View {
HStack(spacing: 0){
ForEach(tabs, id: \.self){ tab in
GeometryReader { geo in
Button {
print(geo.frame(in: .global).midX)
withAnimation(.spring()) {
selectedTab = tab
xAxis = geo.frame(in: .global).midX
}
} label: {
getImage(tab: tab)
.resizable()
.renderingMode(.template)
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.padding(isSelectedTab(tab) ? 15 : 0)
.background(
Color.orange
.opacity(
isSelectedTab(tab) ? 1 : 0
).clipShape(Circle())
)
.matchedGeometryEffect(id: tab, in: animation)
}
.position(x: geo.frame(in: .local).midX, y: geo.frame(in: .local).midY)
.offset(
y: -60
)
.onAppear {
if isSelectedTab(tab) {
xAxis = geo.frame(in: .global).midX
}
}
}
.frame(width: iconSize, height: iconSize)
.overlay(
Rectangle()
.stroke(.red)
)
if tab != tabs.last{
Spacer()
}
}
}
.padding(.horizontal, 30)
.padding(.vertical)
.background(
Color.yellow
.clipShape(BottomNavShape(xAxis: xAxis))
.cornerRadius(15)
)
}
func getImage(tab: Views) -> Image {
switch tab {
case .SETTINGS:
return Image("house")
case .RANKING:
return Image("house")
case .HOME:
return Image("house")
case .SALES:
return Image("house")
case .SEARCHER:
return Image("house")
}
}
enum Views{
case SETTINGS
case RANKING
case HOME
case SALES
case SEARCHER
}
}
底部导航形状:
struct BottomNavShape: Shape{
var xAxis: CGFloat
//Animating path
var animatableData: CGFloat{
get{
return xAxis
}
set{
xAxis = newValue
}
}
func path(in rect: CGRect) -> Path {
return Path{ path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: rect.width, y: 0))
path.addLine(to: CGPoint(x: rect.width, y: rect.height))
path.addLine(to: CGPoint(x: 0, y: rect.height))
let center = CGPoint(x: xAxis, y: rect.midY)
path.move(to: center)
path.addArc(center: center, radius: 15, startAngle: .degrees(0), endAngle:
.degrees(1), clockwise: true)
}
}
}
这些类是复制问题所需的全部。
我正在使用 XCode 13 和 iOS 15。
【问题讨论】:
-
尝试摆脱硬编码偏移
-
偏移量是由于原始代码,选中时圆圈向上。在这个简单的版本中总是向上的。