├── .gitignore
├── DemoApp
├── DemoApp
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── MapView.swift
│ ├── ContentView.swift
│ ├── SceneDelegate.swift
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
└── DemoApp.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
│ └── project.pbxproj
├── Tests
├── LinuxMain.swift
└── FloatingSegmentedControlTests
│ ├── XCTestManifests.swift
│ └── FloatingSegmentedControlTests.swift
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Sources
└── FloatingSegmentedControl
│ ├── utils
│ ├── WidthPreferenceKey.swift
│ ├── TextGeometryWidth.swift
│ ├── HorizontalAlignment.swift
│ └── WidthUpdater.swift
│ ├── views
│ ├── ItemView.swift
│ ├── BlurView.swift
│ └── DividerView.swift
│ └── FloatingSegmentedControl.swift
├── Package.swift
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import FloatingSegmentedControlTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += FloatingSegmentedControlTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Tests/FloatingSegmentedControlTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(FloatingSegmentedControlTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Tests/FloatingSegmentedControlTests/FloatingSegmentedControlTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import FloatingSegmentedControl
3 |
4 | final class FloatingSegmentedControlTests: XCTestCase {
5 | func testExample() {
6 | }
7 |
8 | static var allTests = [
9 | ("testExample", testExample),
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // DemoApp
4 | //
5 | // Created by Darío González Martínez on 19/04/2020.
6 | // Copyright © 2020 Darío González Martínez. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | final class AppDelegate: UIResponder, UIApplicationDelegate { }
13 |
14 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/utils/WidthPreferenceKey.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WidthPreferenceKey.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct WidthPreferenceKey: PreferenceKey {
11 | static var defaultValue = CGFloat(0)
12 |
13 | static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
14 | value = nextValue()
15 | }
16 |
17 | typealias Value = CGFloat
18 | }
19 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "FloatingSegmentedControl",
6 | "repositoryURL": "https://github.com/darioGzlez/FloatingSegmentedControl",
7 | "state": {
8 | "branch": "master",
9 | "revision": "6a99a79ef4be3d64cc3b372b18b85fabbbb78d83",
10 | "version": null
11 | }
12 | }
13 | ]
14 | },
15 | "version": 1
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/utils/TextGeometryWidth.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextGeometryWidth.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct TextGeometryWidth: View {
11 | var body: some View {
12 | GeometryReader { geometry in
13 | Rectangle()
14 | .fill(Color.clear)
15 | .preference(key: WidthPreferenceKey.self, value: geometry.size.width)
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/utils/HorizontalAlignment.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HorizontalAlignment.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import SwiftUI
9 |
10 | extension HorizontalAlignment {
11 | private enum UnderlineLeading: AlignmentID {
12 | static func defaultValue(in d: ViewDimensions) -> CGFloat {
13 | d[.leading]
14 | }
15 | }
16 |
17 | static let underlineLeading = HorizontalAlignment(UnderlineLeading.self)
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/views/ItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemView.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ItemView: View {
11 | var text: String
12 |
13 | var body: some View {
14 | Text(text)
15 | .font(.system(size: 15))
16 | .fontWeight(.semibold)
17 | .lineLimit(1)
18 | .minimumScaleFactor(0.95)
19 | .frame(height: 30)
20 | .padding(.horizontal, 12)
21 | .cornerRadius(16)
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/views/BlurView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BlurView.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import UIKit
9 | import SwiftUI
10 |
11 | struct BlurView: UIViewRepresentable {
12 | var accentColor:UIColor
13 | var style: UIBlurEffect.Style = .systemMaterial
14 |
15 | func makeUIView(context: Context) -> UIVisualEffectView {
16 | UIVisualEffectView(effect: UIBlurEffect(style: style))
17 | }
18 |
19 | func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
20 | uiView.effect = UIBlurEffect(style: style)
21 | uiView.backgroundColor = accentColor
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "FloatingSegmentedControl",
8 | platforms: [
9 | .iOS(.v13)
10 | ],
11 | products: [
12 | .library(
13 | name: "FloatingSegmentedControl",
14 | targets: ["FloatingSegmentedControl"]),
15 | ],
16 | dependencies: [ ],
17 | targets: [
18 | .target(
19 | name: "FloatingSegmentedControl",
20 | dependencies: []),
21 | .testTarget(
22 | name: "FloatingSegmentedControlTests",
23 | dependencies: ["FloatingSegmentedControl"]),
24 | ]
25 | )
26 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/utils/WidthUpdater.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WidthUpdater.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct WidthUpdater: ViewModifier {
11 | @Binding var selectedIndex: Int
12 | @Binding var widths: [CGFloat]
13 | let onSelected: (Int) -> ()
14 | let id: Int
15 |
16 | func body(content: Content) -> some View {
17 | var w: CGFloat = 0
18 | return Group {
19 | if selectedIndex == id {
20 | content.alignmentGuide(.underlineLeading) { d in
21 | w = d.width
22 | return d[.leading]
23 | }.onAppear(perform: {self.widths[self.id] = w})
24 |
25 | } else {
26 | content.onTapGesture {
27 | self.selectedIndex = self.id
28 | self.onSelected(self.selectedIndex)
29 | }
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/MapView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MapView.swift
3 | // DemoApp
4 | //
5 | // Created by Darío González Martínez on 19/04/2020.
6 | // Copyright © 2020 Darío González Martínez. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import MapKit
11 |
12 | struct MapView: UIViewRepresentable {
13 |
14 | class Coordinator: NSObject, MKMapViewDelegate {
15 |
16 | @Binding var mapType: MKMapType
17 |
18 | init(mapType: Binding) {
19 | _mapType = mapType
20 | }
21 |
22 | }
23 |
24 | @Binding var mapType: MKMapType
25 |
26 | func makeCoordinator() -> Coordinator {
27 | Coordinator(mapType: $mapType)
28 | }
29 |
30 | func makeUIView(context: Context) -> MKMapView {
31 | let view = MKMapView(frame: .zero)
32 | view.delegate = context.coordinator
33 | return view
34 | }
35 |
36 | func updateUIView(_ uiView: MKMapView, context: Context) {
37 | uiView.mapType = mapType
38 |
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/views/DividerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DividerView.swift
3 | //
4 | //
5 | // Created by Darío González Martínez on 18/04/2020.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct DividerView: View {
11 | @Binding var buttomTapScale: CGFloat
12 | var allowBlur:Bool
13 | var backgroundColor:UIColor
14 |
15 | var body: some View {
16 | Rectangle()
17 | .padding(.horizontal, 12)
18 | .foregroundColor(.clear)
19 | .background(backgroundView)
20 | //BlurView(accentColor: backgroundColor, style: .systemChromeMaterialDark))
21 |
22 | .cornerRadius(16)
23 | .scaleEffect(buttomTapScale)
24 | .animation(.spring())
25 | }
26 |
27 | var backgroundView: some View {
28 | if allowBlur {
29 | return AnyView(BlurView(accentColor: backgroundColor, style: .systemChromeMaterialDark))
30 | }else{
31 | return AnyView(Color(backgroundColor))
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Darío González
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // DemoApp
4 | //
5 | // Created by Darío González Martínez on 19/04/2020.
6 | // Copyright © 2020 Darío González Martínez. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import MapKit
11 | import FloatingSegmentedControl
12 |
13 | struct ContentView: View {
14 | @State var items = ["Satellite", "Standard"]
15 | @State var mapType: MKMapType = .hybrid
16 |
17 | var body: some View {
18 | ZStack {
19 | MapView(mapType: $mapType).edgesIgnoringSafeArea(.vertical)
20 | VStack {
21 | FloatingSegmentedControlView(
22 | items,
23 | title: "Map view"
24 | onSelected: onSelected)
25 | .padding(.top)
26 | Spacer()
27 | }
28 | }
29 | }
30 |
31 | func onSelected(index: Int) {
32 | switch index {
33 | case 0:
34 | mapType = .hybrid
35 | case 1:
36 | mapType = .standard
37 | default:
38 | mapType = .hybrid
39 | }
40 | }
41 | }
42 |
43 | struct ContentView_Previews: PreviewProvider {
44 | static var previews: some View {
45 | ContentView()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // DemoApp
4 | //
5 | // Created by Darío González Martínez on 19/04/2020.
6 | // Copyright © 2020 Darío González Martínez. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftUI
11 |
12 | final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 |
21 | // Create the SwiftUI view that provides the window contents.
22 | let contentView = ContentView()
23 |
24 | // Use a UIHostingController as window root view controller.
25 | if let windowScene = scene as? UIWindowScene {
26 | let window = UIWindow(windowScene: windowScene)
27 | window.rootViewController = UIHostingController(rootView: contentView)
28 | self.window = window
29 | window.makeKeyAndVisible()
30 | }
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 |
37 |
38 |
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | > SwiftUI reusable implementation of the iOS 13 photos app picker.
4 |
5 | [](http://makeapullrequest.com)
6 |
7 |
8 |
9 | ## :sparkles: Features
10 |
11 | - [x] Auto resizable view based on the number of items and the size of them.
12 | - [x] `OnSelectedItem` method to execute logic for item selection.
13 |
14 | ## :open_book: Next features
15 | - [ ] Ability to customize the color of the bar, items and selector.
16 | - [ ] Customization of disable the drop shadow of the view.
17 |
18 | ## :gear: Requirements
19 |
20 | - iOS 13+
21 | - Xcode 11+
22 |
23 | ### Installation
24 |
25 | Using Xcode's Swift Package Manager, it can be installed by going to `File -> Swift Packages -> Add Package Dependency` and pasting the URL of this repository.
26 |
27 | ```swift
28 | dependencies: [
29 | .package(url: "https://github.com/darioGzlez/FloatingSegmentedControl.git", from: "1.0.0")
30 | ]
31 | ```
32 |
33 | ### Usage
34 |
35 | The floating segmented control takes two parameters: a string array of the elements to display and a callback function that's given the selected element index.
36 |
37 | ```swift
38 | public init(_ items: [String], title: String, onSelected: @escaping (Int) -> ()) {
39 | self.items = items
40 | self.title = title
41 | self.onSelected = onSelected
42 | }
43 | ```
44 |
45 | ## Demo app
46 | Simple app that uses the Floating Segmented Control to switch beetween satellite and standard modes for a `MapView`.
47 |
48 |
49 |
50 |
51 |
52 | |
53 |
54 |
55 | |
56 |
57 |
58 | |
59 |
60 |
61 |
62 | ```swift
63 | import FloatingSegmentedControl
64 |
65 | struct ContentView: View {
66 | @State var items = ["Satellite", "Standad"]
67 | @State var mapType: MKMapType = .hybrid
68 |
69 | var body: some View {
70 | ZStack {
71 | Map(mapType: $mapType).edgesIgnoringSafeArea(.top)
72 | VStack {
73 | FloatingSegmentedControlView(
74 | items,
75 | title: "Map view",
76 | onSelected: onSelected)
77 | .padding(.top)
78 | Spacer()
79 | }
80 | }
81 | }
82 |
83 | func onSelected(index: Int) {
84 | switch index {
85 | case 0:
86 | mapType = .hybrid
87 | case 1:
88 | mapType = .standard
89 | default:
90 | mapType = .hybrid
91 | }
92 | }
93 |
94 | }
95 | ```
96 |
97 | ## Licence
98 | FloatingSegmentedControl is under the MIT license. See the LICENSE file for more info.
99 |
--------------------------------------------------------------------------------
/Sources/FloatingSegmentedControl/FloatingSegmentedControl.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2020 Dario Gonzalez.
3 | //
4 | // Licensed under the MIT license. See the LICENSE file for more info.
5 | //
6 |
7 | import SwiftUI
8 |
9 | /// A control for selecting from a set of mutually exclusive values.
10 | public struct FloatingSegmentedControlView: View {
11 | @State private var widths: [CGFloat] = Array(repeating: 0, count: 100)
12 | @State private var selectedIndex: Int = 0
13 | @State private var buttomTapScale: CGFloat = 1
14 | var selectedTextColor:UIColor
15 | var accentColor:UIColor
16 | var backgroundColor:UIColor
17 | var textColor:UIColor
18 | var allowBlur:Bool
19 | var items: [String]
20 | var title: String
21 | var onSelected: (Int) -> ()
22 |
23 | public var body: some View {
24 | ZStack {
25 | HStack(alignment: .center, spacing: 7) {
26 | ForEach(self.items, id: \.self) { item in
27 | ItemView(text: item)
28 | .foregroundColor(self.selectedIndex == self.items.firstIndex(of: item)! ? Color(textColor) : Color(selectedTextColor))
29 | }
30 | }
31 | .padding(.horizontal, 4.0)
32 |
33 | VStack(alignment: .underlineLeading) {
34 | Button(action: {
35 | withAnimation(.easeIn(duration: 1)) {
36 | self.buttomTapScale = 0.8
37 | }
38 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
39 | withAnimation(.easeIn(duration: 1)) {
40 | self.buttomTapScale = 1
41 | }
42 | }
43 | }) {
44 | DividerView(buttomTapScale: $buttomTapScale, allowBlur: allowBlur, backgroundColor: accentColor)
45 | }
46 | .alignmentGuide(.underlineLeading) { d in d[.leading] }
47 | .frame(width: widths[selectedIndex], height: 30)
48 | .animation(.spring())
49 | .offset(y: 19)
50 |
51 | HStack(alignment: .center, spacing: 7) {
52 | ForEach(self.items, id: \.self) { item in
53 | ItemView(text: item)
54 | .foregroundColor(self.selectedIndex == self.items.firstIndex(of: item)! ? Color(selectedTextColor) : Color(textColor))
55 | .modifier(WidthUpdater(selectedIndex: self.$selectedIndex, widths: self.$widths, onSelected: self.onSelected, id: self.items.firstIndex(of: item)!))
56 | .background(TextGeometryWidth())
57 | .onPreferenceChange(WidthPreferenceKey.self, perform: { self.widths[self.items.firstIndex(of: item)!] = $0 })
58 | }
59 | }
60 | .offset(y: -18.5)
61 | }
62 | .frame(height: 30)
63 | }
64 | .padding(.vertical, 4.0)
65 | .background(mainBackgroundView)
66 | .cornerRadius(16)
67 | .accessibilityElement(children: .ignore)
68 | .accessibility(label: Text("\(self.title)"))
69 | .accessibility(value: Text("\(self.items[self.selectedIndex])"))
70 | .accessibilityAdjustableAction { direction in
71 | switch direction {
72 | case .increment:
73 | if self.selectedIndex < self.items.count - 1 {
74 | self.selectedIndex = self.selectedIndex + 1
75 | self.onSelected(self.selectedIndex)
76 | }
77 |
78 | case .decrement:
79 | if self.selectedIndex > 0 {
80 | self.selectedIndex = self.selectedIndex - 1
81 | self.onSelected(self.selectedIndex)
82 | }
83 | @unknown default: ()
84 | }
85 | }
86 | .shadow(radius: 10)
87 | }
88 |
89 | var mainBackgroundView: some View {
90 | if allowBlur {
91 | return AnyView(BlurView(accentColor: backgroundColor , style: .systemMaterialLight))
92 | }else{
93 | return AnyView(Color(backgroundColor))
94 | }
95 | }
96 | }
97 |
98 |
99 |
100 | extension FloatingSegmentedControlView {
101 |
102 | /// Creates an instance that selects from `items` values.
103 | public init(
104 | _ items: [String],
105 | title: String,
106 | onSelected: @escaping (Int) -> (),
107 | accentColor:UIColor = .gray,
108 | selectedTextColor:UIColor = .gray,
109 | allowBlur:Bool = true,
110 | backgroundColor:UIColor = .lightGray,
111 | textColor:UIColor = .clear
112 | )
113 | {
114 | self.items = items
115 | self.title = title
116 | self.onSelected = onSelected
117 | self.accentColor = accentColor
118 | self.selectedTextColor = selectedTextColor
119 | self.allowBlur = allowBlur
120 | self.backgroundColor = backgroundColor
121 | self.textColor = textColor
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/DemoApp/DemoApp.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | AACEC08A244C699F00157312 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AACEC089244C699F00157312 /* AppDelegate.swift */; };
11 | AACEC08C244C699F00157312 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AACEC08B244C699F00157312 /* SceneDelegate.swift */; };
12 | AACEC08E244C699F00157312 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AACEC08D244C699F00157312 /* ContentView.swift */; };
13 | AACEC090244C69A100157312 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AACEC08F244C69A100157312 /* Assets.xcassets */; };
14 | AACEC093244C69A100157312 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AACEC092244C69A100157312 /* Preview Assets.xcassets */; };
15 | AACEC096244C69A100157312 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AACEC094244C69A100157312 /* LaunchScreen.storyboard */; };
16 | AACEC09F244C6A0200157312 /* FloatingSegmentedControl in Frameworks */ = {isa = PBXBuildFile; productRef = AACEC09E244C6A0200157312 /* FloatingSegmentedControl */; };
17 | AACEC0A1244C6A3400157312 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AACEC0A0244C6A3400157312 /* MapView.swift */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXFileReference section */
21 | AACEC086244C699F00157312 /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
22 | AACEC089244C699F00157312 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
23 | AACEC08B244C699F00157312 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
24 | AACEC08D244C699F00157312 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
25 | AACEC08F244C69A100157312 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
26 | AACEC092244C69A100157312 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
27 | AACEC095244C69A100157312 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | AACEC097244C69A100157312 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | AACEC0A0244C6A3400157312 /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = ""; };
30 | /* End PBXFileReference section */
31 |
32 | /* Begin PBXFrameworksBuildPhase section */
33 | AACEC083244C699F00157312 /* Frameworks */ = {
34 | isa = PBXFrameworksBuildPhase;
35 | buildActionMask = 2147483647;
36 | files = (
37 | AACEC09F244C6A0200157312 /* FloatingSegmentedControl in Frameworks */,
38 | );
39 | runOnlyForDeploymentPostprocessing = 0;
40 | };
41 | /* End PBXFrameworksBuildPhase section */
42 |
43 | /* Begin PBXGroup section */
44 | AACEC07D244C699F00157312 = {
45 | isa = PBXGroup;
46 | children = (
47 | AACEC088244C699F00157312 /* DemoApp */,
48 | AACEC087244C699F00157312 /* Products */,
49 | );
50 | sourceTree = "";
51 | };
52 | AACEC087244C699F00157312 /* Products */ = {
53 | isa = PBXGroup;
54 | children = (
55 | AACEC086244C699F00157312 /* DemoApp.app */,
56 | );
57 | name = Products;
58 | sourceTree = "";
59 | };
60 | AACEC088244C699F00157312 /* DemoApp */ = {
61 | isa = PBXGroup;
62 | children = (
63 | AACEC089244C699F00157312 /* AppDelegate.swift */,
64 | AACEC08B244C699F00157312 /* SceneDelegate.swift */,
65 | AACEC08D244C699F00157312 /* ContentView.swift */,
66 | AACEC08F244C69A100157312 /* Assets.xcassets */,
67 | AACEC094244C69A100157312 /* LaunchScreen.storyboard */,
68 | AACEC097244C69A100157312 /* Info.plist */,
69 | AACEC091244C69A100157312 /* Preview Content */,
70 | AACEC0A0244C6A3400157312 /* MapView.swift */,
71 | );
72 | path = DemoApp;
73 | sourceTree = "";
74 | };
75 | AACEC091244C69A100157312 /* Preview Content */ = {
76 | isa = PBXGroup;
77 | children = (
78 | AACEC092244C69A100157312 /* Preview Assets.xcassets */,
79 | );
80 | path = "Preview Content";
81 | sourceTree = "";
82 | };
83 | /* End PBXGroup section */
84 |
85 | /* Begin PBXNativeTarget section */
86 | AACEC085244C699F00157312 /* DemoApp */ = {
87 | isa = PBXNativeTarget;
88 | buildConfigurationList = AACEC09A244C69A100157312 /* Build configuration list for PBXNativeTarget "DemoApp" */;
89 | buildPhases = (
90 | AACEC082244C699F00157312 /* Sources */,
91 | AACEC083244C699F00157312 /* Frameworks */,
92 | AACEC084244C699F00157312 /* Resources */,
93 | );
94 | buildRules = (
95 | );
96 | dependencies = (
97 | );
98 | name = DemoApp;
99 | packageProductDependencies = (
100 | AACEC09E244C6A0200157312 /* FloatingSegmentedControl */,
101 | );
102 | productName = DemoApp;
103 | productReference = AACEC086244C699F00157312 /* DemoApp.app */;
104 | productType = "com.apple.product-type.application";
105 | };
106 | /* End PBXNativeTarget section */
107 |
108 | /* Begin PBXProject section */
109 | AACEC07E244C699F00157312 /* Project object */ = {
110 | isa = PBXProject;
111 | attributes = {
112 | LastSwiftUpdateCheck = 1140;
113 | LastUpgradeCheck = 1140;
114 | ORGANIZATIONNAME = "Darío González Martínez";
115 | TargetAttributes = {
116 | AACEC085244C699F00157312 = {
117 | CreatedOnToolsVersion = 11.4.1;
118 | };
119 | };
120 | };
121 | buildConfigurationList = AACEC081244C699F00157312 /* Build configuration list for PBXProject "DemoApp" */;
122 | compatibilityVersion = "Xcode 9.3";
123 | developmentRegion = en;
124 | hasScannedForEncodings = 0;
125 | knownRegions = (
126 | en,
127 | Base,
128 | );
129 | mainGroup = AACEC07D244C699F00157312;
130 | packageReferences = (
131 | AACEC09D244C6A0200157312 /* XCRemoteSwiftPackageReference "FloatingSegmentedControl" */,
132 | );
133 | productRefGroup = AACEC087244C699F00157312 /* Products */;
134 | projectDirPath = "";
135 | projectRoot = "";
136 | targets = (
137 | AACEC085244C699F00157312 /* DemoApp */,
138 | );
139 | };
140 | /* End PBXProject section */
141 |
142 | /* Begin PBXResourcesBuildPhase section */
143 | AACEC084244C699F00157312 /* Resources */ = {
144 | isa = PBXResourcesBuildPhase;
145 | buildActionMask = 2147483647;
146 | files = (
147 | AACEC096244C69A100157312 /* LaunchScreen.storyboard in Resources */,
148 | AACEC093244C69A100157312 /* Preview Assets.xcassets in Resources */,
149 | AACEC090244C69A100157312 /* Assets.xcassets in Resources */,
150 | );
151 | runOnlyForDeploymentPostprocessing = 0;
152 | };
153 | /* End PBXResourcesBuildPhase section */
154 |
155 | /* Begin PBXSourcesBuildPhase section */
156 | AACEC082244C699F00157312 /* Sources */ = {
157 | isa = PBXSourcesBuildPhase;
158 | buildActionMask = 2147483647;
159 | files = (
160 | AACEC08A244C699F00157312 /* AppDelegate.swift in Sources */,
161 | AACEC0A1244C6A3400157312 /* MapView.swift in Sources */,
162 | AACEC08C244C699F00157312 /* SceneDelegate.swift in Sources */,
163 | AACEC08E244C699F00157312 /* ContentView.swift in Sources */,
164 | );
165 | runOnlyForDeploymentPostprocessing = 0;
166 | };
167 | /* End PBXSourcesBuildPhase section */
168 |
169 | /* Begin PBXVariantGroup section */
170 | AACEC094244C69A100157312 /* LaunchScreen.storyboard */ = {
171 | isa = PBXVariantGroup;
172 | children = (
173 | AACEC095244C69A100157312 /* Base */,
174 | );
175 | name = LaunchScreen.storyboard;
176 | sourceTree = "";
177 | };
178 | /* End PBXVariantGroup section */
179 |
180 | /* Begin XCBuildConfiguration section */
181 | AACEC098244C69A100157312 /* Debug */ = {
182 | isa = XCBuildConfiguration;
183 | buildSettings = {
184 | ALWAYS_SEARCH_USER_PATHS = NO;
185 | CLANG_ANALYZER_NONNULL = YES;
186 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
187 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
188 | CLANG_CXX_LIBRARY = "libc++";
189 | CLANG_ENABLE_MODULES = YES;
190 | CLANG_ENABLE_OBJC_ARC = YES;
191 | CLANG_ENABLE_OBJC_WEAK = YES;
192 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
193 | CLANG_WARN_BOOL_CONVERSION = YES;
194 | CLANG_WARN_COMMA = YES;
195 | CLANG_WARN_CONSTANT_CONVERSION = YES;
196 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
197 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
198 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
199 | CLANG_WARN_EMPTY_BODY = YES;
200 | CLANG_WARN_ENUM_CONVERSION = YES;
201 | CLANG_WARN_INFINITE_RECURSION = YES;
202 | CLANG_WARN_INT_CONVERSION = YES;
203 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
204 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
205 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
207 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
208 | CLANG_WARN_STRICT_PROTOTYPES = YES;
209 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
210 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
211 | CLANG_WARN_UNREACHABLE_CODE = YES;
212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
213 | COPY_PHASE_STRIP = NO;
214 | DEBUG_INFORMATION_FORMAT = dwarf;
215 | ENABLE_STRICT_OBJC_MSGSEND = YES;
216 | ENABLE_TESTABILITY = YES;
217 | GCC_C_LANGUAGE_STANDARD = gnu11;
218 | GCC_DYNAMIC_NO_PIC = NO;
219 | GCC_NO_COMMON_BLOCKS = YES;
220 | GCC_OPTIMIZATION_LEVEL = 0;
221 | GCC_PREPROCESSOR_DEFINITIONS = (
222 | "DEBUG=1",
223 | "$(inherited)",
224 | );
225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
227 | GCC_WARN_UNDECLARED_SELECTOR = YES;
228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
229 | GCC_WARN_UNUSED_FUNCTION = YES;
230 | GCC_WARN_UNUSED_VARIABLE = YES;
231 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
232 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
233 | MTL_FAST_MATH = YES;
234 | ONLY_ACTIVE_ARCH = YES;
235 | SDKROOT = iphoneos;
236 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
237 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
238 | };
239 | name = Debug;
240 | };
241 | AACEC099244C69A100157312 /* Release */ = {
242 | isa = XCBuildConfiguration;
243 | buildSettings = {
244 | ALWAYS_SEARCH_USER_PATHS = NO;
245 | CLANG_ANALYZER_NONNULL = YES;
246 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
248 | CLANG_CXX_LIBRARY = "libc++";
249 | CLANG_ENABLE_MODULES = YES;
250 | CLANG_ENABLE_OBJC_ARC = YES;
251 | CLANG_ENABLE_OBJC_WEAK = YES;
252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
253 | CLANG_WARN_BOOL_CONVERSION = YES;
254 | CLANG_WARN_COMMA = YES;
255 | CLANG_WARN_CONSTANT_CONVERSION = YES;
256 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
258 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
259 | CLANG_WARN_EMPTY_BODY = YES;
260 | CLANG_WARN_ENUM_CONVERSION = YES;
261 | CLANG_WARN_INFINITE_RECURSION = YES;
262 | CLANG_WARN_INT_CONVERSION = YES;
263 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
264 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
265 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
266 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
267 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
268 | CLANG_WARN_STRICT_PROTOTYPES = YES;
269 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
270 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
271 | CLANG_WARN_UNREACHABLE_CODE = YES;
272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
273 | COPY_PHASE_STRIP = NO;
274 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
275 | ENABLE_NS_ASSERTIONS = NO;
276 | ENABLE_STRICT_OBJC_MSGSEND = YES;
277 | GCC_C_LANGUAGE_STANDARD = gnu11;
278 | GCC_NO_COMMON_BLOCKS = YES;
279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
281 | GCC_WARN_UNDECLARED_SELECTOR = YES;
282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
283 | GCC_WARN_UNUSED_FUNCTION = YES;
284 | GCC_WARN_UNUSED_VARIABLE = YES;
285 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
286 | MTL_ENABLE_DEBUG_INFO = NO;
287 | MTL_FAST_MATH = YES;
288 | SDKROOT = iphoneos;
289 | SWIFT_COMPILATION_MODE = wholemodule;
290 | SWIFT_OPTIMIZATION_LEVEL = "-O";
291 | VALIDATE_PRODUCT = YES;
292 | };
293 | name = Release;
294 | };
295 | AACEC09B244C69A100157312 /* Debug */ = {
296 | isa = XCBuildConfiguration;
297 | buildSettings = {
298 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
299 | CODE_SIGN_STYLE = Automatic;
300 | DEVELOPMENT_ASSET_PATHS = "\"DemoApp/Preview Content\"";
301 | DEVELOPMENT_TEAM = C6W9X4F4G3;
302 | ENABLE_PREVIEWS = YES;
303 | INFOPLIST_FILE = DemoApp/Info.plist;
304 | LD_RUNPATH_SEARCH_PATHS = (
305 | "$(inherited)",
306 | "@executable_path/Frameworks",
307 | );
308 | PRODUCT_BUNDLE_IDENTIFIER = com.darioGonzlez.DemoApp;
309 | PRODUCT_NAME = "$(TARGET_NAME)";
310 | SWIFT_VERSION = 5.0;
311 | TARGETED_DEVICE_FAMILY = "1,2";
312 | };
313 | name = Debug;
314 | };
315 | AACEC09C244C69A100157312 /* Release */ = {
316 | isa = XCBuildConfiguration;
317 | buildSettings = {
318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
319 | CODE_SIGN_STYLE = Automatic;
320 | DEVELOPMENT_ASSET_PATHS = "\"DemoApp/Preview Content\"";
321 | DEVELOPMENT_TEAM = C6W9X4F4G3;
322 | ENABLE_PREVIEWS = YES;
323 | INFOPLIST_FILE = DemoApp/Info.plist;
324 | LD_RUNPATH_SEARCH_PATHS = (
325 | "$(inherited)",
326 | "@executable_path/Frameworks",
327 | );
328 | PRODUCT_BUNDLE_IDENTIFIER = com.darioGonzlez.DemoApp;
329 | PRODUCT_NAME = "$(TARGET_NAME)";
330 | SWIFT_VERSION = 5.0;
331 | TARGETED_DEVICE_FAMILY = "1,2";
332 | };
333 | name = Release;
334 | };
335 | /* End XCBuildConfiguration section */
336 |
337 | /* Begin XCConfigurationList section */
338 | AACEC081244C699F00157312 /* Build configuration list for PBXProject "DemoApp" */ = {
339 | isa = XCConfigurationList;
340 | buildConfigurations = (
341 | AACEC098244C69A100157312 /* Debug */,
342 | AACEC099244C69A100157312 /* Release */,
343 | );
344 | defaultConfigurationIsVisible = 0;
345 | defaultConfigurationName = Release;
346 | };
347 | AACEC09A244C69A100157312 /* Build configuration list for PBXNativeTarget "DemoApp" */ = {
348 | isa = XCConfigurationList;
349 | buildConfigurations = (
350 | AACEC09B244C69A100157312 /* Debug */,
351 | AACEC09C244C69A100157312 /* Release */,
352 | );
353 | defaultConfigurationIsVisible = 0;
354 | defaultConfigurationName = Release;
355 | };
356 | /* End XCConfigurationList section */
357 |
358 | /* Begin XCRemoteSwiftPackageReference section */
359 | AACEC09D244C6A0200157312 /* XCRemoteSwiftPackageReference "FloatingSegmentedControl" */ = {
360 | isa = XCRemoteSwiftPackageReference;
361 | repositoryURL = "https://github.com/darioGzlez/FloatingSegmentedControl";
362 | requirement = {
363 | branch = master;
364 | kind = branch;
365 | };
366 | };
367 | /* End XCRemoteSwiftPackageReference section */
368 |
369 | /* Begin XCSwiftPackageProductDependency section */
370 | AACEC09E244C6A0200157312 /* FloatingSegmentedControl */ = {
371 | isa = XCSwiftPackageProductDependency;
372 | package = AACEC09D244C6A0200157312 /* XCRemoteSwiftPackageReference "FloatingSegmentedControl" */;
373 | productName = FloatingSegmentedControl;
374 | };
375 | /* End XCSwiftPackageProductDependency section */
376 | };
377 | rootObject = AACEC07E244C699F00157312 /* Project object */;
378 | }
379 |
--------------------------------------------------------------------------------