Skip to content

adisve/PillPickerView

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PillPickerView Logo


A SwiftUI library to present a Pill Picker view

  • Highly customizable: PillPickerView offers a wide range of customization options to tailor the appearance of the pills to your needs. You can customize the font, border color, animation, width, height, corner radius, and color scheme of the pills.

  • Easy integration: PillPickerView seamlessly integrates with SwiftUI, making it simple to add the pill picker to your SwiftUI-based app.

  • Select multiple pills: You can select multiple pills simultaneously, and the library provides smooth transitions when adding or removing pills from the selection.

  • Simple API: PillPickerView follows a straightforward API design, making it easy to use. It automatically adjusts the layout of pills to fit within the available space horizontally.

  • Compatibility: Supports iOS 14+, macOS 11+

  • Lightweight and dependency-free: The library has a lightweight structure and does not have any external dependencies, minimizing its impact on your app's size and performance.


How it looks

Static placement

PillPickerView example 1

Flowing placement

PillPickerView example 2

Demo: https://github.com/adisve/PillPickerView/assets/96535657/4f052e75-36f1-4f59-9664-0a187b07de28


📀 Installation

Requires iOS 14+. PillPickerView can be installed through the Swift Package Manager (recommended) or Cocoapods.

Swift Package Manager
Add the Package URL:
Cocoapods
Add this to your Podfile:

https://github.com/adisve/PillPickerView

pod 'PillPickerView'

🧑‍💻 Usage

Creating a PillPickerView

To create a pill picker, you need to follow these steps:

  • Define a struct or enum that conforms to the Pill protocol. This protocol requires implementing the title property, which represents the title of each pill, as well as requiring the object to be Equatable and Hashable.

  • In your SwiftUI view, create a @State or @Binding variable to hold the selected pills. For example:

@State private var selectedPills: [YourPillType] = []

Instantiate a PillPickerView by providing the necessary parameters, such as the list of items and the selected pills binding:

PillPickerView(
    items: yourItemList,
    selectedPills: $selectedPills,
    maxSelectablePills : 5 // Optional Property
)

Here's an example usage of PillPickerView in a SwiftUI view:

import PillPickerView

struct ContentView: View {
    @State private var selectedPills: [YourPillType] = []

    var body: some View {
        VStack {
            // Your other content here
            
            PillPickerView(
                items: yourItemList,
                selectedPills: $selectedPills,
                maxSelectablePill : 5
            )
            
            // Your other content here
        }
    }
}

In the example above, replace YourPillType with your custom pill type and yourItemList with an array of items conforming to the Pill protocol. The maxSelectablePills property is optional. If it is not set, all pills in the array can be selected. If it is set, only the specified number of pills can be selected, and the rest will be disabled.


✨ Customization

PillPickerView offers a range of customization options to tailor the appearance of the pills to your app's design. You can customize the font, colors, animation, size, and other visual aspects of the pills by using the available modifier functions.

The PillPickerView includes a wrapping mechanism that automatically adjusts the layout of pills to fit within the available space. If the pills exceed the horizontal width of the container, the view wraps the excess pills to a new line. This makes it easy to present a large number of pills without worrying about truncation.

You can customize the appearance of the pills by chaining the available modifier functions on the PillPickerView. For example:


PillPickerView(
    items: yourItemList,
    selectedPills: $selectedPills,
    maxSelectablePills : 5
)
.pillFont(.system(size: 16, weight: .semibold))
.pillSelectedForegroundColor(.white)
.pillSelectedBackgroundColor(.blue)
.pillDisabledBackgroundColor(.gray.opacity(0.2))
.pillDisabledForegroundColor(.gray.opacity(0.5))

To switch between the underlying stack style for the content. Choosing .noWrap will invariably cause any text inside the pills to be truncated depending on length, as it will automatically be fitted inside the view and not wrap to a new line. Choosing .wrap will let the pills be dynamically placed an move in the PillPickerView.

.pillStackStyle(.noWrap) // Prevents pills from wrapping to a new line and being dynamic
.pillStackStyle(.wrap) // Default value. Allows pills to move in container

To modify the vertical or horizontal spacing in the PillPickerView

.pillViewVerticalSpacing(10)
.pillViewHorizontalSpacing(5)

To change the font of the pills

.pillFont(.caption)

You can of course chain things together to get a good layout based on your circumstances and requirements.

.pillFont(.title3)
.pillViewHorizontalSpacing(30)

To change the icon used by each pill when it is 'selected'. I advise you to choose something that indicates that the pill will no longer be selected if this icon is pressed, as this is the intended behavior.

.pillSelectedIcon(Image(systemName: "xmark"))

To change the background color of a not selected and selected pill, respectively

.pillNormalBackgroundColor(.green)
.pillSelectedBackgroundColor(.blue)

To change the foreground color of a not selected and selected pill, respectively

.pillNormalForegroundColor(.orange)
.pillSelectedForegroundColor(.white)

The height and width of the pills can also be set, but they will be treated as the minimum width of each pill

.pillMinWidth(20)
.pillMinHeight(10)

This adds trailing and leading icons to the view, but only displays the trailing icons when the element has been selected.

.pillLeadingIcon(Image(systemName: "popcorn"))
.pillTrailingIcon(Image(systemName: "checkmark"))
.pillTrailingOnlySelected(true) /// Only when item is selected

Corner radius and border color can also be changed easily

.pillBorderColor(.green)
.pillCornerRadius(40)

You can also change the animation used when a pill is pressed or wrapped to a newline

.pillAnimation(.easeInOut)

Padding can also be applied horizontally or vertically

.pillPaddingHorizontal(10)
.pillPaddingVertical(10)

If maxSelectablePills is set you can adjust the disabled state colors

.pillDisabledBackgroundColor(.gray.opacity(0.2))
.pillDisabledForegroundColor(.gray.opacity(0.5))

License

 Created by A. Veletanlic (github.com/adisve) on 5/20/23.
 Copyright © 2023 A. Veletanlic. All rights reserved.

 MIT License

 Copyright (c) 2023 A. Veletanlic

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

Stats