Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iPad Bottom Sheet, but at the Bottom ✨ #100

Merged
merged 8 commits into from Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BottomSheetSwiftUI.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'BottomSheetSwiftUI'
spec.version = '3.0.2'
spec.version = '3.1.0'
spec.swift_version = '5.5'
spec.authors = { 'Lucas Zischka' => 'lucas_zischka@outlook.com' }
spec.license = { :type => 'MIT', :file => 'LICENSE.txt' }
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
BottomSheet Changelog
==================

#### v3.1.0
- Added the `.iPadFloatingSheet(Bool)` modifier
- Added the `.sheetWidth(BottomSheetWidth)` modifier
- Added the `.accountForKeyboardHeight(Bool)` modifier #97

#### v3.0.2
- Added `.customThreshold(Double)` modifier #8, #88

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ The ViewModifiers are used to customise the look and feel of the BottomSheet.
- Changing the threshold does not affect whether either option is enabled.
- The default threshold is 30% (0.3).

`.iPadFloatingSheet(Bool)`: Makes it possible to make the sheet appear like on iPhone.

`.sheetWidth(BottomSheetWidth)`: Makes it possible to configure a custom sheet width.
- Can be relative through `BottomSheetWidth.relative(x)`.
- Can be absolute through `BottomSheetWidth.absolute(x)`.
- Set to `BottomSheetWidth.platformDefault` to let the library decide the width.

`.accountForKeyboardHeight(Bool)`: Adds padding to the bottom of the main content when the keyboard appears so all of the main content is visible.
- If the height of the sheet is smaller than the height of the keyboard, this modifier will not make the content visible.
- This behaviour is not active on Mac, because it would not make sense there.

## BottomSheetPosition

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// BottomSheet+AccountForKeyboardHeight.swift
//
//
// Created by Robin Pel on 06/09/2022.
//

import Foundation

public extension BottomSheet {

/// Adds padding to the bottom of the main content when the keyboard appears so all of the main content is visible.
///
/// - Note: If the height of the sheet is smaller than the height of the keyboard, this modifier will not make the content visible.
///
/// - Note: This behaviour is not active on Mac, because it would not make sense there.
///
/// - Parameters:
/// - bool: A boolean whether the option is enabled.
///
/// - Returns: A BottomSheet with its main content shifted up to account for the keyboard when it has appeared.
func accountForKeyboardHeight(_ bool: Bool = true) -> BottomSheet {
self.configuration.accountForKeyboardHeight = bool
return self
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// BottomSheet+IPadFloatingSheet.swift
//
//
// Created by Robin Pel on 05/09/2022.
//

import Foundation

public extension BottomSheet {

/// Makes it possible to make the sheet appear like on iPhone.
///
/// - Parameters:
/// - bool: A boolean whether the option is enabled.
///
/// - Returns: A BottomSheet that will actually appear at the bottom.
func iPadFloatingSheet(_ bool: Bool = true) -> BottomSheet {
self.configuration.iPadFloatingSheet = bool
return self
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// BottomSheet+SheetWidth.swift
//
//
// Created by Robin Pel on 05/09/2022.
//

import Foundation

public extension BottomSheet {

/// Makes it possible to configure a custom sheet width.
///
/// - Parameters:
/// - width: The width to use for the bottom sheet.
///
/// - Returns: A BottomSheet with the configured width.
func sheetWidth(_ width: BottomSheetWidth = .platformDefault) -> BottomSheet {
self.configuration.sheetWidth = width
return self
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,44 @@ import SwiftUI

internal extension BottomSheetView {

// For iPad and Mac support
var isIPadOrMac: Bool {
var isIPad: Bool {
#if os(macOS)
return true
return false
#else
if self.horizontalSizeClass == .regular && self.verticalSizeClass == .regular {
return true
} else {
return false
}
return self.horizontalSizeClass == .regular && self.verticalSizeClass == .regular
#endif
}

var iPadAndMacTopPadding: CGFloat {
if self.isIPadOrMac {
#if !os(macOS)
return UIApplication.shared.windows.first?.safeAreaInsets.top ?? 10
var isMac: Bool {
#if os(macOS)
return true
#else
return false
#endif
}

var isIPadOrMac: Bool {
return self.isIPad || self.isMac
}

var isIPadFloating: Bool {
return self.isIPad && self.configuration.iPadFloatingSheet
}

var isIPadFloatingOrMac: Bool {
return self.isIPadFloating || self.isMac
}

var isIPadBottom: Bool {
return self.isIPad && !self.configuration.iPadFloatingSheet
}

var topPadding: CGFloat {
if self.isIPadFloatingOrMac {
#if os(macOS)
return NSApplication.shared.mainMenu?.menuBarHeight ?? 20
#else
return UIApplication.shared.windows.first?.safeAreaInsets.top ?? 10
#endif
} else {
return 0
Expand All @@ -53,8 +72,8 @@ internal extension BottomSheetView {

// The height of the safe area when position is bottom
var bottomPositionSafeAreaHeight: CGFloat {
// Only add safe area when `dynamicBottom` and not on iPad or Mac
if self.bottomSheetPosition == .dynamicBottom && !self.isIPadOrMac {
// Only add safe area when `dynamicBottom` and not on iPad floating or Mac
if self.bottomSheetPosition == .dynamicBottom && !self.isIPadFloatingOrMac {
#if !os(macOS)
// Safe area as height (iPhone)
return UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 20
Expand All @@ -63,7 +82,7 @@ internal extension BottomSheetView {
return 0
#endif
} else {
// When not `.dynamicBottom` or when iPad or Mac don't add safe area
// When not `.dynamicBottom` or when iPad floating or Mac don't add safe area
return 0
}
}
Expand All @@ -79,7 +98,7 @@ internal extension BottomSheetView {
// The maximum height of the BottomSheet
func maxBottomSheetHeight(with geometry: GeometryProxy) -> CGFloat {
// Screen height without safe areas and padding
return geometry.size.height - (self.isIPadOrMac ? 20 : 0) - self.iPadAndMacTopPadding
return geometry.size.height - (self.isIPadFloatingOrMac ? 20 : 0) - self.topPadding
}

// The current height of the BottomSheet (without translation)
Expand Down Expand Up @@ -136,18 +155,42 @@ internal extension BottomSheetView {

// For iPhone landscape, iPad and Mac support
func width(with geometry: GeometryProxy) -> CGFloat {
switch self.configuration.sheetWidth {

case .platformDefault:
return self.platformDefaultWidth(with: geometry)

case .relative(let width):
// Don't allow the width to be smaller than zero, or larger than one
return geometry.size.width * max(
0,
min(
1,
width
)
)

case .absolute(let width):
return max(
0,
width
)
}
}

func platformDefaultWidth(with geometry: GeometryProxy) -> CGFloat {
#if os(macOS)
// On Mac use 30% of the width
return geometry.size.width * 0.3
#else
if self.isIPadOrMac {
if self.isIPad {
// On iPad use 30% of the width
return geometry.size.width * 0.3
} else if UIDevice.current.orientation.isLandscape {
// On iPhone landscape use of the 40% width
// On iPhone landscape use 40% of the width
return geometry.size.width * 0.4
} else {
// On iPhone portrait use of the 100% width
// On iPhone portrait use 100% of the width
return geometry.size.width
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ internal extension BottomSheetView {
// Perform custom onChanged action
self.configuration.onDragChanged(value)

// Update translation; on iPad and Mac the drag direction is reversed
self.translation = self.isIPadOrMac ? -value.translation.height : value.translation.height
// Update translation; on iPad floating and Mac the drag direction is reversed
self.translation = self.isIPadFloatingOrMac ? -value.translation.height : value.translation.height
// Dismiss the keyboard on drag
self.endEditing()
}
Expand Down Expand Up @@ -51,8 +51,8 @@ internal extension BottomSheetView {

// Notify the ScrollView that the user is dragging
self.dragState = .none
// Update translation; on iPad and Mac the drag direction is reversed
self.translation = self.isIPadOrMac ? -value.translation.height : value.translation.height
// Update translation; on iPad floating and Mac the drag direction is reversed
self.translation = self.isIPadFloatingOrMac ? -value.translation.height : value.translation.height
}

// Dismiss the keyboard on dragging/scrolling
Expand Down
Loading