diff --git a/Sources/BottomSheet/BottomSheet.swift b/Sources/BottomSheet/BottomSheet.swift index d4b136b..b3febaf 100644 --- a/Sources/BottomSheet/BottomSheet.swift +++ b/Sources/BottomSheet/BottomSheet.swift @@ -17,6 +17,7 @@ public struct BottomSheet: View { @State private var previousDragValue: DragGesture.Value? @Binding var isPresented: Bool + @State var gestureEnded: Bool private let height: CGFloat private let topBarHeight: CGFloat private let topBarCornerRadius: CGFloat @@ -24,6 +25,7 @@ public struct BottomSheet: View { private let contentBackgroundColor: Color private let topBarBackgroundColor: Color private let showTopIndicator: Bool + private let animation: Animation public init( isPresented: Binding, @@ -33,11 +35,13 @@ public struct BottomSheet: View { topBarBackgroundColor: Color = Color(.systemBackground), contentBackgroundColor: Color = Color(.systemBackground), showTopIndicator: Bool, + animation: Animation = .interactiveSpring(), @ViewBuilder content: () -> Content ) { self.topBarBackgroundColor = topBarBackgroundColor self.contentBackgroundColor = contentBackgroundColor self._isPresented = isPresented + self._gestureEnded = State(initialValue: true) self.height = height self.topBarHeight = topBarHeight if let topBarCornerRadius = topBarCornerRadius { @@ -45,6 +49,7 @@ public struct BottomSheet: View { } else { self.topBarCornerRadius = topBarHeight / 3 } + self.animation = animation self.showTopIndicator = showTopIndicator self.content = content() } @@ -64,7 +69,7 @@ public struct BottomSheet: View { .frame(height: self.height - min(self.draggedOffset*2, 0)) .background(self.contentBackgroundColor) .cornerRadius(self.topBarCornerRadius, corners: [.topLeft, .topRight]) - .animation(.interactiveSpring()) + .animation(self.gestureEnded ? .interactiveSpring() : self.animation) .offset(y: self.isPresented ? (geometry.size.height/2 - self.height/2 + geometry.safeAreaInsets.bottom + self.draggedOffset) : (geometry.size.height/2 + self.height/2 + geometry.safeAreaInsets.bottom)) } } @@ -75,8 +80,11 @@ public struct BottomSheet: View { .black .opacity(grayBackgroundOpacity) .edgesIgnoringSafeArea(.all) - .animation(.interactiveSpring()) - .onTapGesture { self.isPresented = false } + .animation(self.gestureEnded ? .interactiveSpring() : self.animation) + .onTapGesture { + self.gestureEnded = false + self.isPresented = false + } } fileprivate func topBar(geometry: GeometryProxy) -> some View { @@ -91,7 +99,6 @@ public struct BottomSheet: View { .gesture( DragGesture() .onChanged({ (value) in - let offsetY = value.translation.height self.draggedOffset = offsetY @@ -105,6 +112,7 @@ public struct BottomSheet: View { return } } + self.gestureEnded = true self.previousDragValue = value }) @@ -113,6 +121,8 @@ public struct BottomSheet: View { if offsetY > self.dragToDismissThreshold { self.isPresented = false } + + self.gestureEnded = false self.draggedOffset = 0 }) ) diff --git a/Sources/BottomSheet/ViewExtension.swift b/Sources/BottomSheet/ViewExtension.swift index 106c356..d7e4d92 100644 --- a/Sources/BottomSheet/ViewExtension.swift +++ b/Sources/BottomSheet/ViewExtension.swift @@ -17,6 +17,7 @@ public extension View { contentBackgroundColor: Color = Color(.systemBackground), topBarBackgroundColor: Color = Color(.systemBackground), showTopIndicator: Bool = true, + animation: Animation = .interactiveSpring(), @ViewBuilder content: @escaping () -> Content ) -> some View { ZStack { @@ -28,6 +29,7 @@ public extension View { topBarBackgroundColor: topBarBackgroundColor, contentBackgroundColor: contentBackgroundColor, showTopIndicator: showTopIndicator, + animation: animation, content: content) } } diff --git a/iOS Example/Sources/ContentView.swift b/iOS Example/Sources/ContentView.swift index 3ea0554..0f7ce94 100644 --- a/iOS Example/Sources/ContentView.swift +++ b/iOS Example/Sources/ContentView.swift @@ -26,7 +26,8 @@ struct ContentView: View { height: 370, topBarHeight: 16, topBarCornerRadius: 16, - showTopIndicator: false + showTopIndicator: false, + animation: .spring() ) { MapSettingView() }