Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29beea0ff9 | |||
| 1e16d9c1fb | |||
| 31d7a2a301 | |||
| 5f1d49b0bd | |||
| ee66f218ca | |||
| 3a0831a334 | |||
| add2f9ba4f | |||
| ca6a8d5c16 | |||
| 84eba1aefa | |||
| 289ea4c971 | |||
| 821b03376c | |||
| 19fe1cffef |
+37
-14
@@ -10,6 +10,19 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macOS-11
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: "Swift 5.4"
|
||||
run: xcodebuild -scheme FloatingPanel SWIFT_VERSION=5.4 clean build
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.5.1.app/Contents/Developer
|
||||
- name: "Swift 5.5"
|
||||
run: xcodebuild -scheme FloatingPanel SWIFT_VERSION=5.5 clean build
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.0.app/Contents/Developer
|
||||
|
||||
build_compat:
|
||||
runs-on: macOS-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
@@ -24,9 +37,22 @@ jobs:
|
||||
- name: "Swift 5.3"
|
||||
run: xcodebuild -scheme FloatingPanel SWIFT_VERSION=5.3 clean build
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.3.app/Contents/Developer
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer
|
||||
|
||||
testing:
|
||||
runs-on: macOS-11
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: "Testing in iOS 14.5"
|
||||
run: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=14.5,name=iPhone 12 Pro'
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.5.1.app/Contents/Developer
|
||||
- name: "Testing in iOS 15.0"
|
||||
run: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=15.0,name=iPhone 13 Pro'
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.0.app/Contents/Developer
|
||||
|
||||
testing_compat:
|
||||
runs-on: macOS-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
@@ -34,15 +60,15 @@ jobs:
|
||||
run: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=13.7,name=iPhone 11 Pro'
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_11.7.app/Contents/Developer
|
||||
- name: "Testing in iOS 14.3"
|
||||
run: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=14.3,name=iPhone 12 Pro'
|
||||
- name: "Testing in iOS 14.4"
|
||||
run: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=14.4,name=iPhone 12 Pro'
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.3.app/Contents/Developer
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer
|
||||
|
||||
example:
|
||||
runs-on: macOS-10.15
|
||||
runs-on: macOS-11
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.3.app/Contents/Developer
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.0.app/Contents/Developer
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: "Build Maps"
|
||||
@@ -53,26 +79,23 @@ jobs:
|
||||
run: xcodebuild -workspace FloatingPanel.xcworkspace -scheme Samples -sdk iphonesimulator clean build
|
||||
|
||||
swiftpm:
|
||||
runs-on: macOS-10.15
|
||||
runs-on: macOS-11
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_12.3.app/Contents/Developer
|
||||
DEVELOPER_DIR: /Applications/Xcode_13.0.app/Contents/Developer
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: "Swift Package build"
|
||||
run: swift build -Xswiftc "-sdk" -Xswiftc "`xcrun --sdk iphonesimulator --show-sdk-path`" -Xswiftc "-target" -Xswiftc "x86_64-apple-ios14.3-simulator"
|
||||
|
||||
carthage:
|
||||
runs-on: macOS-10.15
|
||||
env:
|
||||
# Carthage doesn't fix issues on Xcode 12: https://github.com/Carthage/Carthage/releases/tag/0.36.0
|
||||
DEVELOPER_DIR: /Applications/Xcode_11.7.app/Contents/Developer
|
||||
runs-on: macOS-11
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: "Carthage build"
|
||||
run: carthage build --no-skip-current
|
||||
run: carthage build --use-xcframeworks --no-skip-current
|
||||
|
||||
cocoapods:
|
||||
runs-on: macOS-10.15
|
||||
runs-on: macOS-11
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: "CocoaPods: pod lib lint"
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
language: objective-c
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
env:
|
||||
global:
|
||||
- LANG=en_US.UTF-8
|
||||
- LC_ALL=en_US.UTF-8
|
||||
jobs:
|
||||
include:
|
||||
- stage: "Tests"
|
||||
script: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=10.3.1,name=iPhone SE (1st generation)'
|
||||
osx_image: xcode11.6
|
||||
name: "iPhone SE (iOS 10.3)"
|
||||
- script: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=11.4,name=iPhone 7'
|
||||
osx_image: xcode11.6
|
||||
name: "iPhone 7 (iOS 11.4)"
|
||||
- script: xcodebuild clean test -scheme FloatingPanel -workspace FloatingPanel.xcworkspace -destination 'platform=iOS Simulator,OS=12.4,name=iPhone X'
|
||||
osx_image: xcode11.6
|
||||
name: "iPhone X (iOS 12.4)"
|
||||
@@ -0,0 +1,426 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 55;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
6467E8642699AC5F00565F4F /* SurfaceAppearance+phone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6467E8632699AC5F00565F4F /* SurfaceAppearance+phone.swift */; };
|
||||
6467E86A2699B19D00565F4F /* SearchPanelPhoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6467E8692699B19D00565F4F /* SearchPanelPhoneDelegate.swift */; };
|
||||
649A122926C14D0900DAB961 /* UIHostingController+ignoreKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649A122826C14D0900DAB961 /* UIHostingController+ignoreKeyboard.swift */; };
|
||||
649A122D26C168CF00DAB961 /* View+floatingPanelGrabberHandlePadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649A122C26C168CF00DAB961 /* View+floatingPanelGrabberHandlePadding.swift */; };
|
||||
64A5B7232691323900BCAA05 /* MapsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B7222691323900BCAA05 /* MapsApp.swift */; };
|
||||
64A5B7252691323900BCAA05 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B7242691323900BCAA05 /* ContentView.swift */; };
|
||||
64A5B734269133DC00BCAA05 /* FloatingPanel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 64A5B733269133DC00BCAA05 /* FloatingPanel.framework */; };
|
||||
64A5B735269133DC00BCAA05 /* FloatingPanel.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 64A5B733269133DC00BCAA05 /* FloatingPanel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
64A5B738269134CA00BCAA05 /* VisualEffectBlur.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B737269134CA00BCAA05 /* VisualEffectBlur.swift */; };
|
||||
64A5B73C2691469900BCAA05 /* FloatingPanelContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B73B2691469900BCAA05 /* FloatingPanelContentView.swift */; };
|
||||
64A5B73E269147DC00BCAA05 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B73D269147DC00BCAA05 /* SearchBar.swift */; };
|
||||
64A5B7402691532400BCAA05 /* ResultsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B73F2691532400BCAA05 /* ResultsList.swift */; };
|
||||
64A5B7422691541A00BCAA05 /* HostingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A5B7412691541A00BCAA05 /* HostingCell.swift */; };
|
||||
64F7E83126AD70EB00A0E0F7 /* View+floatingPanelContentInsetAdjustmentBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F7E82C26AD70EB00A0E0F7 /* View+floatingPanelContentInsetAdjustmentBehavior.swift */; };
|
||||
64F7E83226AD70EB00A0E0F7 /* View+floatingPanelContentMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F7E82D26AD70EB00A0E0F7 /* View+floatingPanelContentMode.swift */; };
|
||||
64F7E83326AD70EB00A0E0F7 /* FloatingPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F7E82E26AD70EB00A0E0F7 /* FloatingPanelView.swift */; };
|
||||
64F7E83426AD70EB00A0E0F7 /* View+floatingPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F7E82F26AD70EB00A0E0F7 /* View+floatingPanel.swift */; };
|
||||
64F7E83526AD70EB00A0E0F7 /* View+floatingPanelSurfaceAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F7E83026AD70EB00A0E0F7 /* View+floatingPanelSurfaceAppearance.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
64A5B736269133DC00BCAA05 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
64A5B735269133DC00BCAA05 /* FloatingPanel.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
6467E8632699AC5F00565F4F /* SurfaceAppearance+phone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SurfaceAppearance+phone.swift"; sourceTree = "<group>"; };
|
||||
6467E8692699B19D00565F4F /* SearchPanelPhoneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchPanelPhoneDelegate.swift; sourceTree = "<group>"; };
|
||||
649A122826C14D0900DAB961 /* UIHostingController+ignoreKeyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIHostingController+ignoreKeyboard.swift"; sourceTree = "<group>"; };
|
||||
649A122C26C168CF00DAB961 /* View+floatingPanelGrabberHandlePadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+floatingPanelGrabberHandlePadding.swift"; sourceTree = "<group>"; };
|
||||
64A5B71F2691323900BCAA05 /* Maps-SwiftUI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Maps-SwiftUI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
64A5B7222691323900BCAA05 /* MapsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapsApp.swift; sourceTree = "<group>"; };
|
||||
64A5B7242691323900BCAA05 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
64A5B733269133DC00BCAA05 /* FloatingPanel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FloatingPanel.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
64A5B737269134CA00BCAA05 /* VisualEffectBlur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualEffectBlur.swift; sourceTree = "<group>"; };
|
||||
64A5B73B2691469900BCAA05 /* FloatingPanelContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPanelContentView.swift; sourceTree = "<group>"; };
|
||||
64A5B73D269147DC00BCAA05 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
|
||||
64A5B73F2691532400BCAA05 /* ResultsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultsList.swift; sourceTree = "<group>"; };
|
||||
64A5B7412691541A00BCAA05 /* HostingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingCell.swift; sourceTree = "<group>"; };
|
||||
64F7E82C26AD70EB00A0E0F7 /* View+floatingPanelContentInsetAdjustmentBehavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+floatingPanelContentInsetAdjustmentBehavior.swift"; sourceTree = "<group>"; };
|
||||
64F7E82D26AD70EB00A0E0F7 /* View+floatingPanelContentMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+floatingPanelContentMode.swift"; sourceTree = "<group>"; };
|
||||
64F7E82E26AD70EB00A0E0F7 /* FloatingPanelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingPanelView.swift; sourceTree = "<group>"; };
|
||||
64F7E82F26AD70EB00A0E0F7 /* View+floatingPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+floatingPanel.swift"; sourceTree = "<group>"; };
|
||||
64F7E83026AD70EB00A0E0F7 /* View+floatingPanelSurfaceAppearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+floatingPanelSurfaceAppearance.swift"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
64A5B71C2691323900BCAA05 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
64A5B734269133DC00BCAA05 /* FloatingPanel.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
64A5B7162691323900BCAA05 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
64A5B7212691323900BCAA05 /* Maps */,
|
||||
64A5B7202691323900BCAA05 /* Products */,
|
||||
64A5B732269133DC00BCAA05 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
64A5B7202691323900BCAA05 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
64A5B71F2691323900BCAA05 /* Maps-SwiftUI.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
64A5B7212691323900BCAA05 /* Maps */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
64F7E82B26AD70EB00A0E0F7 /* FloatingPanel */,
|
||||
64BE55702691BBB0006D98BD /* Representable */,
|
||||
64A5B7222691323900BCAA05 /* MapsApp.swift */,
|
||||
64A5B7242691323900BCAA05 /* ContentView.swift */,
|
||||
64A5B73B2691469900BCAA05 /* FloatingPanelContentView.swift */,
|
||||
6467E8692699B19D00565F4F /* SearchPanelPhoneDelegate.swift */,
|
||||
6467E8632699AC5F00565F4F /* SurfaceAppearance+phone.swift */,
|
||||
64A5B7412691541A00BCAA05 /* HostingCell.swift */,
|
||||
64A5B73F2691532400BCAA05 /* ResultsList.swift */,
|
||||
);
|
||||
path = Maps;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
64A5B732269133DC00BCAA05 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
64A5B733269133DC00BCAA05 /* FloatingPanel.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
64BE55702691BBB0006D98BD /* Representable */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
64A5B73D269147DC00BCAA05 /* SearchBar.swift */,
|
||||
64A5B737269134CA00BCAA05 /* VisualEffectBlur.swift */,
|
||||
);
|
||||
path = Representable;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
64F7E82B26AD70EB00A0E0F7 /* FloatingPanel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
64F7E82E26AD70EB00A0E0F7 /* FloatingPanelView.swift */,
|
||||
64F7E82F26AD70EB00A0E0F7 /* View+floatingPanel.swift */,
|
||||
64F7E82C26AD70EB00A0E0F7 /* View+floatingPanelContentInsetAdjustmentBehavior.swift */,
|
||||
64F7E82D26AD70EB00A0E0F7 /* View+floatingPanelContentMode.swift */,
|
||||
64F7E83026AD70EB00A0E0F7 /* View+floatingPanelSurfaceAppearance.swift */,
|
||||
649A122C26C168CF00DAB961 /* View+floatingPanelGrabberHandlePadding.swift */,
|
||||
649A122826C14D0900DAB961 /* UIHostingController+ignoreKeyboard.swift */,
|
||||
);
|
||||
path = FloatingPanel;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
64A5B71E2691323900BCAA05 /* Maps-SwiftUI */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 64A5B72D2691323A00BCAA05 /* Build configuration list for PBXNativeTarget "Maps-SwiftUI" */;
|
||||
buildPhases = (
|
||||
64A5B71B2691323900BCAA05 /* Sources */,
|
||||
64A5B71C2691323900BCAA05 /* Frameworks */,
|
||||
64A5B71D2691323900BCAA05 /* Resources */,
|
||||
64A5B736269133DC00BCAA05 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Maps-SwiftUI";
|
||||
productName = "Maps-SwiftUI";
|
||||
productReference = 64A5B71F2691323900BCAA05 /* Maps-SwiftUI.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
64A5B7172691323900BCAA05 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1300;
|
||||
LastUpgradeCheck = 1300;
|
||||
TargetAttributes = {
|
||||
64A5B71E2691323900BCAA05 = {
|
||||
CreatedOnToolsVersion = 13.0;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 64A5B71A2691323900BCAA05 /* Build configuration list for PBXProject "Maps-SwiftUI" */;
|
||||
compatibilityVersion = "Xcode 13.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 64A5B7162691323900BCAA05;
|
||||
productRefGroup = 64A5B7202691323900BCAA05 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
64A5B71E2691323900BCAA05 /* Maps-SwiftUI */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
64A5B71D2691323900BCAA05 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
64A5B71B2691323900BCAA05 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6467E86A2699B19D00565F4F /* SearchPanelPhoneDelegate.swift in Sources */,
|
||||
64A5B7422691541A00BCAA05 /* HostingCell.swift in Sources */,
|
||||
64A5B738269134CA00BCAA05 /* VisualEffectBlur.swift in Sources */,
|
||||
64A5B7402691532400BCAA05 /* ResultsList.swift in Sources */,
|
||||
6467E8642699AC5F00565F4F /* SurfaceAppearance+phone.swift in Sources */,
|
||||
64F7E83226AD70EB00A0E0F7 /* View+floatingPanelContentMode.swift in Sources */,
|
||||
64A5B7252691323900BCAA05 /* ContentView.swift in Sources */,
|
||||
64A5B7232691323900BCAA05 /* MapsApp.swift in Sources */,
|
||||
64A5B73C2691469900BCAA05 /* FloatingPanelContentView.swift in Sources */,
|
||||
649A122D26C168CF00DAB961 /* View+floatingPanelGrabberHandlePadding.swift in Sources */,
|
||||
64F7E83326AD70EB00A0E0F7 /* FloatingPanelView.swift in Sources */,
|
||||
64F7E83426AD70EB00A0E0F7 /* View+floatingPanel.swift in Sources */,
|
||||
64F7E83526AD70EB00A0E0F7 /* View+floatingPanelSurfaceAppearance.swift in Sources */,
|
||||
64F7E83126AD70EB00A0E0F7 /* View+floatingPanelContentInsetAdjustmentBehavior.swift in Sources */,
|
||||
64A5B73E269147DC00BCAA05 /* SearchBar.swift in Sources */,
|
||||
649A122926C14D0900DAB961 /* UIHostingController+ignoreKeyboard.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
64A5B72B2691323A00BCAA05 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
64A5B72C2691323A00BCAA05 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
64A5B72E2691323A00BCAA05 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.scenee.Maps-SwiftUI";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
64A5B72F2691323A00BCAA05 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.scenee.Maps-SwiftUI";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
64A5B71A2691323900BCAA05 /* Build configuration list for PBXProject "Maps-SwiftUI" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
64A5B72B2691323A00BCAA05 /* Debug */,
|
||||
64A5B72C2691323A00BCAA05 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
64A5B72D2691323A00BCAA05 /* Build configuration list for PBXNativeTarget "Maps-SwiftUI" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
64A5B72E2691323A00BCAA05 /* Debug */,
|
||||
64A5B72F2691323A00BCAA05 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 64A5B7172691323900BCAA05 /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
import MapKit
|
||||
|
||||
struct ContentView: View {
|
||||
@State private var region = MKCoordinateRegion(
|
||||
center: CLLocationCoordinate2D(latitude: 37.623198015869235, longitude: -122.43066818432008),
|
||||
span: MKCoordinateSpan(latitudeDelta: 0.4425100023575723, longitudeDelta: 0.28543697435880233)
|
||||
)
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Map(coordinateRegion: $region)
|
||||
.ignoresSafeArea()
|
||||
statusBarBlur
|
||||
}
|
||||
}
|
||||
|
||||
private var statusBarBlur: some View {
|
||||
GeometryReader { geometry in
|
||||
VisualEffectBlur()
|
||||
.frame(height: geometry.safeAreaInsets.top)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
import SwiftUI
|
||||
|
||||
/// A proxy for exposing the methods of the floating panel controller.
|
||||
public struct FloatingPanelProxy {
|
||||
/// The associated floating panel controller.
|
||||
public weak var fpc: FloatingPanelController?
|
||||
|
||||
/// Tracks the specified scroll view to correspond with the scroll.
|
||||
///
|
||||
/// - Parameter scrollView: Specify a scroll view to continuously and
|
||||
/// seamlessly work in concert with interactions of the surface view.
|
||||
public func track(scrollView: UIScrollView) {
|
||||
fpc?.track(scrollView: scrollView)
|
||||
}
|
||||
|
||||
/// Moves the floating panel to the specified position.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - floatingPanelState: The state to move to.
|
||||
/// - animated: `true` to animate the transition to the new state; `false`
|
||||
/// otherwise.
|
||||
public func move(
|
||||
to floatingPanelState: FloatingPanelState,
|
||||
animated: Bool,
|
||||
completion: (() -> Void)? = nil
|
||||
) {
|
||||
fpc?.move(to: floatingPanelState, animated: animated, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
/// A view with an associated floating panel.
|
||||
struct FloatingPanelView<Content: View, FloatingPanelContent: View>: UIViewControllerRepresentable {
|
||||
/// A type that conforms to the `FloatingPanelControllerDelegate` protocol.
|
||||
var delegate: FloatingPanelControllerDelegate?
|
||||
|
||||
/// The behavior for determining the adjusted content offsets.
|
||||
@Environment(\.contentInsetAdjustmentBehavior) var contentInsetAdjustmentBehavior
|
||||
|
||||
/// Constants that define how a panel content fills in the surface.
|
||||
@Environment(\.contentMode) var contentMode
|
||||
|
||||
/// The floating panel grabber handle offset.
|
||||
@Environment(\.grabberHandlePadding) var grabberHandlePadding
|
||||
|
||||
/// The floating panel `surfaceView` appearance.
|
||||
@Environment(\.surfaceAppearance) var surfaceAppearance
|
||||
|
||||
/// The view builder that creates the floating panel parent view content.
|
||||
@ViewBuilder var content: Content
|
||||
|
||||
/// The view builder that creates the floating panel content.
|
||||
@ViewBuilder var floatingPanelContent: (FloatingPanelProxy) -> FloatingPanelContent
|
||||
|
||||
public func makeUIViewController(context: Context) -> UIHostingController<Content> {
|
||||
let hostingController = UIHostingController(rootView: content)
|
||||
hostingController.view.backgroundColor = nil
|
||||
// We need to wait for the current runloop cycle to complete before our
|
||||
// view is actually added (into the view hierarchy), otherwise the
|
||||
// environment is not ready yet.
|
||||
DispatchQueue.main.async {
|
||||
context.coordinator.setupFloatingPanel(hostingController)
|
||||
}
|
||||
return hostingController
|
||||
}
|
||||
|
||||
public func updateUIViewController(
|
||||
_ uiViewController: UIHostingController<Content>,
|
||||
context: Context
|
||||
) {
|
||||
context.coordinator.updateIfNeeded()
|
||||
}
|
||||
|
||||
public func makeCoordinator() -> Coordinator {
|
||||
Coordinator(parent: self)
|
||||
}
|
||||
|
||||
/// `FloatingPanelView` coordinator.
|
||||
///
|
||||
/// Responsible to setup the view hierarchy and floating panel.
|
||||
final class Coordinator {
|
||||
private let parent: FloatingPanelView<Content, FloatingPanelContent>
|
||||
private lazy var fpc = FloatingPanelController()
|
||||
|
||||
init(parent: FloatingPanelView<Content, FloatingPanelContent>) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
func setupFloatingPanel(_ parentViewController: UIViewController) {
|
||||
updateIfNeeded()
|
||||
let panelContent = parent.floatingPanelContent(FloatingPanelProxy(fpc: fpc))
|
||||
let hostingViewController = UIHostingController(
|
||||
rootView: panelContent,
|
||||
ignoresKeyboard: true
|
||||
)
|
||||
hostingViewController.view.backgroundColor = nil
|
||||
fpc.set(contentViewController: hostingViewController)
|
||||
fpc.addPanel(toParent: parentViewController, at: 1, animated: false)
|
||||
}
|
||||
|
||||
func updateIfNeeded() {
|
||||
if fpc.contentInsetAdjustmentBehavior != parent.contentInsetAdjustmentBehavior {
|
||||
fpc.contentInsetAdjustmentBehavior = parent.contentInsetAdjustmentBehavior
|
||||
}
|
||||
if fpc.contentMode != parent.contentMode {
|
||||
fpc.contentMode = parent.contentMode
|
||||
}
|
||||
if fpc.delegate !== parent.delegate {
|
||||
fpc.delegate = parent.delegate
|
||||
}
|
||||
if fpc.surfaceView.grabberHandlePadding != parent.grabberHandlePadding {
|
||||
fpc.surfaceView.grabberHandlePadding = parent.grabberHandlePadding
|
||||
}
|
||||
if fpc.surfaceView.appearance != parent.surfaceAppearance {
|
||||
fpc.surfaceView.appearance = parent.surfaceAppearance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// This extension makes sure SwiftUI views are not affected by iOS keyboard.
|
||||
///
|
||||
/// Credits to https://steipete.me/posts/disabling-keyboard-avoidance-in-swiftui-uihostingcontroller/
|
||||
extension UIHostingController {
|
||||
public convenience init(rootView: Content, ignoresKeyboard: Bool) {
|
||||
self.init(rootView: rootView)
|
||||
|
||||
if ignoresKeyboard {
|
||||
guard let viewClass = object_getClass(view) else { return }
|
||||
|
||||
let viewSubclassName = String(
|
||||
cString: class_getName(viewClass)
|
||||
).appending("_IgnoresKeyboard")
|
||||
|
||||
if let viewSubclass = NSClassFromString(viewSubclassName) {
|
||||
object_setClass(view, viewSubclass)
|
||||
} else {
|
||||
guard
|
||||
let viewClassNameUtf8 = (viewSubclassName as NSString).utf8String,
|
||||
let viewSubclass = objc_allocateClassPair(viewClass, viewClassNameUtf8, 0)
|
||||
else { return }
|
||||
|
||||
if let method = class_getInstanceMethod(
|
||||
viewClass,
|
||||
NSSelectorFromString("keyboardWillShowWithNotification:")
|
||||
) {
|
||||
let keyboardWillShow: @convention(block) (AnyObject, AnyObject) -> Void = { _, _ in }
|
||||
class_addMethod(
|
||||
viewSubclass,
|
||||
NSSelectorFromString("keyboardWillShowWithNotification:"),
|
||||
imp_implementationWithBlock(keyboardWillShow),
|
||||
method_getTypeEncoding(method)
|
||||
)
|
||||
}
|
||||
objc_registerClassPair(viewSubclass)
|
||||
object_setClass(view, viewSubclass)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
/// Presents a floating panel using the given closure as its content.
|
||||
///
|
||||
/// The modifier's content view builder receives a `FloatingPanelProxy`
|
||||
/// instance; you use the proxy's methods to interact with the associated
|
||||
/// `FloatingPanelController`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - delegate: A type that conforms to the
|
||||
/// `FloatingPanelControllerDelegate` protocol. You have comprehensive
|
||||
/// control over the floating panel behavior when you use a delegate.
|
||||
/// - floatingPanelContent: The floating panel content. This view builder
|
||||
/// receives a `FloatingPanelProxy` instance that you use to interact
|
||||
/// with the `FloatingPanelController`.
|
||||
public func floatingPanel<FloatingPanelContent: View>(
|
||||
delegate: FloatingPanelControllerDelegate? = nil,
|
||||
@ViewBuilder _ floatingPanelContent: @escaping (_: FloatingPanelProxy) -> FloatingPanelContent
|
||||
) -> some View {
|
||||
FloatingPanelView(
|
||||
delegate: delegate,
|
||||
content: { self },
|
||||
floatingPanelContent: floatingPanelContent
|
||||
)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
import SwiftUI
|
||||
|
||||
struct ContentInsetKey: EnvironmentKey {
|
||||
static var defaultValue: FloatingPanelController.ContentInsetAdjustmentBehavior = .always
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
/// The behavior for determining the adjusted content offsets.
|
||||
var contentInsetAdjustmentBehavior: FloatingPanelController.ContentInsetAdjustmentBehavior {
|
||||
get { self[ContentInsetKey.self] }
|
||||
set { self[ContentInsetKey.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
/// Sets the content inset adjustment behavior for floating panels within
|
||||
/// this view.
|
||||
///
|
||||
/// Use this modifier to set a specific content inset adjustment behavior
|
||||
/// for floating panel instances within a view:
|
||||
///
|
||||
/// MainView()
|
||||
/// .floatingPanel { _ in
|
||||
/// FloatingPanelContent()
|
||||
/// }
|
||||
/// .floatingPanelContentInsetAdjustmentBehavior(.never)
|
||||
///
|
||||
/// - Parameter contentInsetAdjustmentBehavior: The content inset adjustment
|
||||
/// behavior to set.
|
||||
public func floatingPanelContentInsetAdjustmentBehavior(
|
||||
_ contentInsetAdjustmentBehavior: FloatingPanelController.ContentInsetAdjustmentBehavior
|
||||
) -> some View {
|
||||
environment(\.contentInsetAdjustmentBehavior, contentInsetAdjustmentBehavior)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
import SwiftUI
|
||||
|
||||
struct ContentModeKey: EnvironmentKey {
|
||||
static var defaultValue: FloatingPanelController.ContentMode = .static
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
/// Used to determine how the floating panel controller lays out the content
|
||||
/// view when the surface position changes.
|
||||
var contentMode: FloatingPanelController.ContentMode {
|
||||
get { self[ContentModeKey.self] }
|
||||
set { self[ContentModeKey.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
/// Sets the content mode for floating panels within this view.
|
||||
///
|
||||
/// Use this modifier to set a specific content mode for floating panel
|
||||
/// instances within a view:
|
||||
///
|
||||
/// MainView()
|
||||
/// .floatingPanel { _ in
|
||||
/// FloatingPanelContent()
|
||||
/// }
|
||||
/// .floatingPanelContentMode(.static)
|
||||
///
|
||||
/// - Parameter contentMode: The content mode to set.
|
||||
public func floatingPanelContentMode(
|
||||
_ contentMode: FloatingPanelController.ContentMode
|
||||
) -> some View {
|
||||
environment(\.contentMode, contentMode)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
import SwiftUI
|
||||
|
||||
struct GrabberHandlePaddingKey: EnvironmentKey {
|
||||
static var defaultValue: CGFloat = 6.0
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
/// The offset of the grabber handle from the interactive edge.
|
||||
var grabberHandlePadding: CGFloat {
|
||||
get { self[GrabberHandlePaddingKey.self] }
|
||||
set { self[GrabberHandlePaddingKey.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
/// Sets the grabber handle padding for floating panels within this view.
|
||||
///
|
||||
/// Use this modifier to set a specific padding to floating panel instances
|
||||
/// within a view:
|
||||
///
|
||||
/// MainView()
|
||||
/// .floatingPanel { _ in
|
||||
/// FloatingPanelContent()
|
||||
/// }
|
||||
/// .floatingPanelGrabberHandlePadding(16)
|
||||
///
|
||||
/// - Parameter padding: The grabber handle padding to set.
|
||||
public func floatingPanelGrabberHandlePadding(
|
||||
_ padding: CGFloat
|
||||
) -> some View {
|
||||
environment(\.grabberHandlePadding, padding)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
import SwiftUI
|
||||
|
||||
struct SurfaceAppearanceKey: EnvironmentKey {
|
||||
static var defaultValue = SurfaceAppearance()
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
/// The appearance of a surface view.
|
||||
var surfaceAppearance: SurfaceAppearance {
|
||||
get { self[SurfaceAppearanceKey.self] }
|
||||
set { self[SurfaceAppearanceKey.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
/// Sets the surface appearance for floating panels within this view.
|
||||
///
|
||||
/// Use this modifier to set a specific surface appearance for floating
|
||||
/// panel instances within a view:
|
||||
///
|
||||
/// MainView()
|
||||
/// .floatingPanel { _ in
|
||||
/// FloatingPanelContent()
|
||||
/// }
|
||||
/// .floatingPanelSurfaceAppearance(.transparent)
|
||||
///
|
||||
/// extension SurfaceAppearance {
|
||||
/// static var transparent: SurfaceAppearance {
|
||||
/// let appearance = SurfaceAppearance()
|
||||
/// appearance.backgroundColor = .clear
|
||||
/// return appearance
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// - Parameter surfaceAppearance: The surface appearance to set.
|
||||
public func floatingPanelSurfaceAppearance(
|
||||
_ surfaceAppearance: SurfaceAppearance
|
||||
) -> some View {
|
||||
environment(\.surfaceAppearance, surfaceAppearance)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct FloatingPanelContentView: View {
|
||||
@State private var searchText = ""
|
||||
@State private var isShowingCancelButton = false
|
||||
var proxy: FloatingPanelProxy
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
searchBar
|
||||
resultsList
|
||||
}
|
||||
// 👇🏻 for the floating panel grabber handle.
|
||||
.padding(.top, 6)
|
||||
.background(
|
||||
VisualEffectBlur(blurStyle: .systemMaterial)
|
||||
// ⚠️ If the `VisualEffectBlur` view receives taps, it's going
|
||||
// to mess up with the whole panel and render it
|
||||
// non-interactive, make sure it never receives any taps.
|
||||
.allowsHitTesting(false)
|
||||
)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
|
||||
var searchBar: some View {
|
||||
SearchBar(
|
||||
"Search for a place or address",
|
||||
text: $searchText,
|
||||
isShowingCancelButton: $isShowingCancelButton
|
||||
) { isFocused in
|
||||
proxy.move(to: isFocused ? .full : .half, animated: true)
|
||||
isShowingCancelButton = isFocused
|
||||
} onCancel: {
|
||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||
}
|
||||
}
|
||||
|
||||
var resultsList: some View {
|
||||
ResultsList(onScrollViewCreated: proxy.track(scrollView:))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// A `UITableViewCell` that accepts a SwiftUI view as its content.
|
||||
///
|
||||
/// Credits to https://noahgilmore.com/blog/swiftui-self-sizing-cells/ .
|
||||
public final class HostingCell<Content: View>: UITableViewCell {
|
||||
private let hostingController = UIHostingController<Content?>(
|
||||
rootView: nil,
|
||||
ignoresKeyboard: true
|
||||
)
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
hostingController.view.backgroundColor = nil
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func set(rootView: Content, parentController: UIViewController) {
|
||||
hostingController.rootView = rootView
|
||||
hostingController.view.invalidateIntrinsicContentSize()
|
||||
|
||||
let requiresControllerMove = hostingController.parent != parentController
|
||||
if requiresControllerMove {
|
||||
parentController.addChild(hostingController)
|
||||
}
|
||||
|
||||
if !contentView.subviews.contains(hostingController.view) {
|
||||
contentView.addSubview(hostingController.view)
|
||||
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.addConstraints([
|
||||
hostingController.view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
|
||||
hostingController.view.topAnchor.constraint(equalTo: contentView.topAnchor),
|
||||
hostingController.view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
|
||||
hostingController.view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
if requiresControllerMove {
|
||||
hostingController.didMove(toParent: parentController)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct MapsApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
.floatingPanel(delegate: SearchPanelPhoneDelegate()) { proxy in
|
||||
FloatingPanelContentView(proxy: proxy)
|
||||
}
|
||||
.floatingPanelSurfaceAppearance(.phone)
|
||||
.floatingPanelContentMode(.fitToBounds)
|
||||
.floatingPanelContentInsetAdjustmentBehavior(.never)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// UIKit's `UISearchBar`brought to SwiftUI.
|
||||
public struct SearchBar: UIViewRepresentable {
|
||||
var title: String
|
||||
@Binding var text: String
|
||||
@Binding var isShowingCancelButton: Bool
|
||||
var onEditingChanged: (Bool) -> Void
|
||||
var onCancel: () -> Void
|
||||
|
||||
public init(
|
||||
_ title: String = "",
|
||||
text: Binding<String>,
|
||||
isShowingCancelButton: Binding<Bool>,
|
||||
onEditingChanged: @escaping (Bool) -> Void = { _ in },
|
||||
onCancel: @escaping () -> Void
|
||||
) {
|
||||
self.title = title
|
||||
self._text = text
|
||||
self._isShowingCancelButton = isShowingCancelButton
|
||||
self.onEditingChanged = onEditingChanged
|
||||
self.onCancel = onCancel
|
||||
}
|
||||
|
||||
public func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
|
||||
let searchBar = UISearchBar(frame: .zero)
|
||||
searchBar.searchBarStyle = .minimal
|
||||
searchBar.isTranslucent = true
|
||||
searchBar.placeholder = title
|
||||
searchBar.delegate = context.coordinator
|
||||
searchBar.autocapitalizationType = .none
|
||||
return searchBar
|
||||
}
|
||||
|
||||
public func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchBar>) {
|
||||
uiView.text = text
|
||||
uiView.placeholder = title
|
||||
uiView.setShowsCancelButton(isShowingCancelButton, animated: true)
|
||||
}
|
||||
|
||||
public func makeCoordinator() -> SearchBar.Coordinator {
|
||||
Coordinator(parent: self)
|
||||
}
|
||||
|
||||
public class Coordinator: NSObject, UISearchBarDelegate {
|
||||
var parent: SearchBar
|
||||
|
||||
init(parent: SearchBar) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
|
||||
parent.text = searchText
|
||||
}
|
||||
|
||||
public func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
|
||||
parent.onEditingChanged(true)
|
||||
}
|
||||
|
||||
public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
|
||||
searchBar.resignFirstResponder()
|
||||
}
|
||||
|
||||
public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
|
||||
parent.onEditingChanged(false)
|
||||
}
|
||||
|
||||
public func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
|
||||
parent.onCancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@available(iOS, introduced: 13, deprecated: 15, message: "Use iOS 15 material API.")
|
||||
public struct VisualEffectBlur<Content: View>: UIViewRepresentable {
|
||||
var blurStyle: UIBlurEffect.Style = .systemMaterial
|
||||
var vibrancyStyle: UIVibrancyEffectStyle? = nil
|
||||
@ViewBuilder var content: Content
|
||||
|
||||
public func makeUIView(context: Context) -> UIVisualEffectView {
|
||||
context.coordinator.blurView
|
||||
}
|
||||
|
||||
public func updateUIView(_ view: UIVisualEffectView, context: Context) {
|
||||
context.coordinator.update(
|
||||
content: content,
|
||||
blurStyle: blurStyle,
|
||||
vibrancyStyle: vibrancyStyle
|
||||
)
|
||||
}
|
||||
|
||||
public func makeCoordinator() -> Coordinator {
|
||||
Coordinator(content: content)
|
||||
}
|
||||
|
||||
public class Coordinator {
|
||||
let blurView = UIVisualEffectView()
|
||||
let vibrancyView = UIVisualEffectView()
|
||||
let hostingController: UIHostingController<Content>
|
||||
|
||||
init(content: Content) {
|
||||
hostingController = UIHostingController(rootView: content)
|
||||
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
hostingController.view.backgroundColor = nil
|
||||
blurView.contentView.addSubview(vibrancyView)
|
||||
|
||||
blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
vibrancyView.contentView.addSubview(hostingController.view)
|
||||
vibrancyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
}
|
||||
|
||||
func update(content: Content, blurStyle: UIBlurEffect.Style, vibrancyStyle: UIVibrancyEffectStyle?) {
|
||||
hostingController.rootView = content
|
||||
|
||||
let blurEffect = UIBlurEffect(style: blurStyle)
|
||||
blurView.effect = blurEffect
|
||||
|
||||
if let vibrancyStyle = vibrancyStyle {
|
||||
vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect, style: vibrancyStyle)
|
||||
} else {
|
||||
vibrancyView.effect = nil
|
||||
}
|
||||
|
||||
hostingController.view.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension VisualEffectBlur where Content == EmptyView {
|
||||
init(
|
||||
blurStyle: UIBlurEffect.Style = .systemMaterial,
|
||||
vibrancyStyle: UIVibrancyEffectStyle? = nil
|
||||
) {
|
||||
self.init(blurStyle: blurStyle, vibrancyStyle: vibrancyStyle) {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ResultsList: UIViewControllerRepresentable {
|
||||
var onScrollViewCreated: (_ scrollView: UIScrollView) -> Void
|
||||
|
||||
func makeUIViewController(
|
||||
context: Context
|
||||
) -> ResultsTableViewController {
|
||||
let rtvc = ResultsTableViewController()
|
||||
onScrollViewCreated(rtvc.tableView)
|
||||
return rtvc
|
||||
}
|
||||
|
||||
func updateUIViewController(
|
||||
_ uiViewController: ResultsTableViewController,
|
||||
context: Context
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
final class ResultsTableViewController: UITableViewController {
|
||||
private let reuseIdentifier = "HostingCell<ResultListCell>"
|
||||
|
||||
private enum Section: CaseIterable {
|
||||
case main
|
||||
}
|
||||
|
||||
private struct TableViewItem: Hashable {
|
||||
let color: Color
|
||||
let symbolName: String
|
||||
let title: String
|
||||
let description: String
|
||||
}
|
||||
|
||||
private var dataSource: UITableViewDiffableDataSource<Section, TableViewItem>?
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.backgroundColor = nil
|
||||
tableView.register(HostingCell<ResultListCell>.self, forCellReuseIdentifier: reuseIdentifier)
|
||||
configureDataSource()
|
||||
}
|
||||
|
||||
// MARK: UITableViewDataSource
|
||||
|
||||
private func configureDataSource() {
|
||||
dataSource = UITableViewDiffableDataSource
|
||||
<Section, TableViewItem>(tableView: tableView) { [weak self] tableView, _, tableItem -> UITableViewCell? in
|
||||
self?.tableView(tableView, cellForTableViewItem: tableItem)
|
||||
}
|
||||
tableView.dataSource = dataSource
|
||||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<Section, TableViewItem>()
|
||||
snapshot.appendSections([.main])
|
||||
let results: [TableViewItem] = (1...100).map {
|
||||
TableViewItem(
|
||||
color: Color(red: 255 / 255.0, green: 94 / 255.0 , blue: 94 / 255.0),
|
||||
symbolName: "heart.fill",
|
||||
title: "Favorites",
|
||||
description: "\($0) Places"
|
||||
)
|
||||
}
|
||||
snapshot.appendItems(results, toSection: .main)
|
||||
dataSource?.apply(snapshot, animatingDifferences: false)
|
||||
}
|
||||
|
||||
private func tableView(
|
||||
_ tableView: UITableView,
|
||||
cellForTableViewItem tableViewItem: TableViewItem
|
||||
) -> UITableViewCell {
|
||||
let cell: HostingCell<ResultListCell> = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier) as! HostingCell<ResultListCell>
|
||||
setupResultTableViewCell(
|
||||
cell,
|
||||
color: tableViewItem.color,
|
||||
symbolName: tableViewItem.symbolName,
|
||||
title: tableViewItem.title,
|
||||
description: tableViewItem.description
|
||||
)
|
||||
return cell
|
||||
}
|
||||
|
||||
private func setupResultTableViewCell(
|
||||
_ cell: HostingCell<ResultListCell>,
|
||||
color: Color,
|
||||
symbolName: String,
|
||||
title: String,
|
||||
description: String
|
||||
) {
|
||||
cell.set(
|
||||
rootView: ResultListCell(
|
||||
color: color,
|
||||
symbolName: symbolName,
|
||||
title: title,
|
||||
description: description
|
||||
),
|
||||
parentController: self
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: UITableViewDelegate
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
didSelectRowAt indexPath: IndexPath
|
||||
) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
struct ResultListCell: View {
|
||||
let color: Color
|
||||
let symbolName: String
|
||||
let title: String
|
||||
let description: String
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Image(systemName: symbolName)
|
||||
.foregroundColor(.white)
|
||||
.font(.headline)
|
||||
.padding(8)
|
||||
.background(Circle().fill(color))
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(title)
|
||||
.font(.system(size: 20, weight: .bold))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Text(description)
|
||||
.font(.system(size: 13))
|
||||
.foregroundColor(Color(.secondaryLabel))
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
|
||||
final class SearchPanelPhoneDelegate: FloatingPanelControllerDelegate {
|
||||
func floatingPanelWillBeginDragging(_ vc: FloatingPanelController) {
|
||||
if vc.state == .full {
|
||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2021 the FloatingPanel authors. All rights reserved. MIT license.
|
||||
|
||||
import FloatingPanel
|
||||
|
||||
extension FloatingPanel.SurfaceAppearance {
|
||||
static var phone: SurfaceAppearance {
|
||||
let appearance = SurfaceAppearance()
|
||||
appearance.cornerCurve = .continuous
|
||||
appearance.cornerRadius = 8.0
|
||||
appearance.backgroundColor = .clear
|
||||
return appearance
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class ViewController: UIViewController {
|
||||
}
|
||||
|
||||
func layoutPanelForPhone() {
|
||||
fpc.track(scrollView: searchVC.tableView) // Only track the tabvle view on iPhone
|
||||
fpc.track(scrollView: searchVC.tableView) // Only track the table view on iPhone
|
||||
fpc.addPanel(toParent: self, animated: true)
|
||||
fpc.setAppearanceForPhone()
|
||||
detailFpc.setAppearanceForPhone()
|
||||
|
||||
@@ -87,12 +87,12 @@ class DebugTableViewController: InspectableViewController {
|
||||
}
|
||||
}
|
||||
|
||||
func execute(for vc: DebugTableViewController) {
|
||||
func execute(for vc: DebugTableViewController, sourceView: UIView) {
|
||||
switch self {
|
||||
case .animateScroll:
|
||||
vc.animateScroll()
|
||||
case .changeContentSize:
|
||||
vc.changeContentSize()
|
||||
vc.changeContentSize(sourceView: sourceView)
|
||||
case .moveToFull:
|
||||
vc.moveToFull()
|
||||
case .moveToHalf:
|
||||
@@ -165,8 +165,8 @@ class DebugTableViewController: InspectableViewController {
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
private func execute(command: Command) {
|
||||
command.execute(for: self)
|
||||
private func execute(command: Command, sourceView: UIView) {
|
||||
command.execute(for: self, sourceView: sourceView)
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -177,7 +177,7 @@ class DebugTableViewController: InspectableViewController {
|
||||
}
|
||||
|
||||
@objc
|
||||
private func changeContentSize() {
|
||||
private func changeContentSize(sourceView: UIView) {
|
||||
let actionSheet = UIAlertController(title: "Change content size", message: "", preferredStyle: .actionSheet)
|
||||
actionSheet.addAction(UIAlertAction(title: "Large", style: .default, handler: { (_) in
|
||||
self.itemHeight = 66.0
|
||||
@@ -201,6 +201,11 @@ class DebugTableViewController: InspectableViewController {
|
||||
self.changeItems(3)
|
||||
}))
|
||||
|
||||
if let popoverController = actionSheet.popoverPresentationController {
|
||||
popoverController.sourceView = sourceView
|
||||
popoverController.sourceRect = sourceView.bounds
|
||||
}
|
||||
|
||||
self.present(actionSheet, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@@ -250,7 +255,8 @@ extension DebugTableViewController: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
print("DebugTableViewController -- select row \(indexPath.row)")
|
||||
guard let action = Command(rawValue: indexPath.row) else { return }
|
||||
execute(command: action)
|
||||
let cell = tableView.cellForRow(at: indexPath)
|
||||
execute(command: action, sourceView: cell ?? tableView)
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
|
||||
@@ -41,6 +41,10 @@ final class TabBarContentViewController: UIViewController {
|
||||
fpc.addPanel(toParent: self)
|
||||
|
||||
|
||||
if #available(iOS 15, *) {
|
||||
tabBarController?.tabBar.scrollEdgeAppearance = UITabBarAppearance()
|
||||
}
|
||||
|
||||
switch tabBarItem.tag {
|
||||
case 1:
|
||||
fpc.behavior = TwoTabBarPanelBehavior()
|
||||
|
||||
@@ -36,7 +36,7 @@ static FloatingPanelState *_lastQuart;
|
||||
[fpc setBehavior:[MyFloatingPanelBehavior new]];
|
||||
[fpc setRemovalInteractionEnabled:NO];
|
||||
|
||||
[fpc addPanelToParent:self at:self.view.subviews.count animated:NO];
|
||||
[fpc addPanelToParent:self at:self.view.subviews.count animated:NO completion:nil];
|
||||
[fpc moveToState:FloatingPanelState.Tip animated:true completion:nil];
|
||||
|
||||
[self updateAppearance: fpc];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "FloatingPanel"
|
||||
s.version = "2.4.0"
|
||||
s.version = "2.5.0"
|
||||
s.summary = "FloatingPanel is a clean and easy-to-use UI component of a floating panel interface."
|
||||
s.description = <<-DESC
|
||||
FloatingPanel is a clean and easy-to-use UI component for a new interface introduced in Apple Maps, Shortcuts and Stocks app.
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
<Group
|
||||
location = "group:Examples"
|
||||
name = "Examples">
|
||||
<FileRef
|
||||
location = "group:Maps-SwiftUI/Maps-SwiftUI.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Maps/Maps.xcodeproj">
|
||||
</FileRef>
|
||||
|
||||
@@ -7,5 +7,5 @@ import UIKit
|
||||
public class BackdropView: UIView {
|
||||
|
||||
/// The gesture recognizer for tap gestures to dismiss a panel.
|
||||
public var dismissalTapGestureRecognizer: UITapGestureRecognizer!
|
||||
@objc public var dismissalTapGestureRecognizer: UITapGestureRecognizer!
|
||||
}
|
||||
|
||||
@@ -837,6 +837,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
private func tearDownActiveInteraction() {
|
||||
guard panGestureRecognizer.isEnabled else { return }
|
||||
// Cancel the pan gesture so that panningEnd(with:velocity:) is called
|
||||
panGestureRecognizer.isEnabled = false
|
||||
panGestureRecognizer.isEnabled = true
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.4.0</string>
|
||||
<string>2.5.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
</dict>
|
||||
|
||||
@@ -766,6 +766,13 @@ class CoreTests: XCTestCase {
|
||||
(#line, tipPos, CGPoint(x: 0.0, y: 1000.0), .hidden),
|
||||
])
|
||||
}
|
||||
|
||||
func test_keep_pan_gesture_disabled() {
|
||||
let fpc = FloatingPanelController()
|
||||
fpc.panGestureRecognizer.isEnabled = false
|
||||
fpc.showForTest()
|
||||
XCTAssertFalse(fpc.panGestureRecognizer.isEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
private class FloatingPanelLayout3Positions: FloatingPanelTestLayout {
|
||||
|
||||
Reference in New Issue
Block a user