GithubHelp home page GithubHelp logo

mrasterisco / combopicker Goto Github PK

View Code? Open in Web Editor NEW
9.0 2.0 0.0 3.77 MB

A SwiftUI implementation of a picker that also allows direct input.

License: MIT License

Swift 100.00%
combo combobox picker swiftui

combopicker's Introduction

ComboPicker

ComboPicker is a SwiftUI view that allows users to input a value by selecting from a predefined set or by typing a custom one.

ComboPicker

Installation

ComboPicker is available through Swift Package Manager.

.package(url: "https://github.com/MrAsterisco/ComboPicker", from: "<see GitHub releases>")

Latest Release

To find out the latest version, look at the Releases tab of this repository.

Usage

ComboPicker can display any type that conforms to the ComboPickerModel protocol. The following example shows a model that wraps a Int:

public struct ExampleModel: ComboPickerModel {
  public static func ==(lhs: ExampleModel, rhs: ExampleModel) -> Bool {
    lhs.value == rhs.value
  }

  public let id = UUID()
  public let value: Int
  
  // Default initializer.
  public init(value: Int) {
    self.value = value
  }
  
  // Initializer to convert user input into a value.
  public init?(customValue: String) {
    guard let doubleValue = NumberFormatter().number(from: customValue)?.intValue else { return nil }
    self.init(value: doubleValue)
  }
  
  // Convert the value to prefill the manual input field.
  public var valueForManualInput: String? {
    NumberFormatter().string(from: .init(value: value))
  }
}

You also have to provide an implementation of ValueFormatterType, so that the ComboPicker knows how to represent values in the Pickers. The following example illustrates a simple formatter for the model implemented above:

final class ExampleModelFormatter: ValueFormatterType {
  func string(from value: ExampleModel) -> String {
    "# \(NumberFormatter().string(from: .init(value: value.value)) ?? "")"
  }
}

Once you have a collection of models and the formatter implementation, building a ComboPicker is easy:

@State private var content: [ExampleModel]
@State private var selection: ExampleModel

ComboPicker(
  title: "Pick a number",
  manualTitle: "Custom...",
  valueFormatter: ExampleModelFormatter(),
  content: $content,
  value: $selection
)

Platform Behaviors

ComboPicker adapts to the platform to provide an easy and accessible experience regardless of the device.

iOS & iPadOS

On iOS and iPadOS, the ComboPicker shows a one-line UIPickerView that the user can scroll. If the user taps on it, a text field for manual input appears.

ComboPicker

If necessary, you can customize the keyboard type for the manual input field:

.keyboardType(.numberPad)

Note: because of limitations of the SwiftUI Picker regarding the gestures handling, as well as the ability of showing and using multiple wheel pickers in the same screen, ComboPicker is currently relying on a UIViewRepresentable implementation of a UIPickerView. You can read more about the current limitations here.

watchOS

On watchOS, the ComboPickershows a normal Picker that the user can scroll using their fingers or the digital crown. If the user taps on it, a text field for manual input appears.

ComboPicker

There is no support for specifying the keyboard type, at the moment, as Apple doesn't provide a way to do so on watchOS.

macOS

On macOS, the ComboPicker becomes an NSComboBox. Users will be able to select options or type custom ones directly into the component.

See the Apple docs for further information on how combo boxes work.

tvOS

On tvOS, the ComboPicker shows a Picker followed by a TextField. The user can move on the picker or scroll down to the text field and input a custom value.

ComboPicker

If necessary, you can customize the keyboard type for the manual input field:

.keyboardType(.numberPad)

Compatibility

ComboPicker requires iOS 15.0 or later, macOS 12.0 or later, watchOS 8.0 or later and tvOS 15.0 or later.

Contributions

All contributions to expand the library are welcome. Fork the repo, make the changes you want, and open a Pull Request.

If you make changes to the codebase, I am not enforcing a coding style, but I may ask you to make changes based on how the rest of the library is made.

Status

This library is under active development. Even if most of the APIs are pretty straightforward, they may change in the future; but you don't have to worry about that, because releases will follow Semantic Versioning 2.0.0.

License

ComboPicker is distributed under the MIT license. See LICENSE for details.

combopicker's People

Contributors

mrasterisco avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

combopicker's Issues

Multiple ComboPicker in the same view conflict with each other

Overview

Because of a limitation on how the Picker works in SwiftUI, when displaying two (or more) ComboPicker in the same view, only one of them will work correctly. The last added will intercept all tap and scroll events and will prevent the other pickers from being used.

This is only a problem on iOS and iPadOS.

Proposed Solution

This could be fixed by rolling-out our own picker implementation, instead of relying on the system one. This would also have the benefit of allowing custom sizes (instead of forcing the picker to be as wide as its container).

Layout issues in List

Overview

There are some layout issues when embedding the picker in a list, possibly because of the additional space that the picker would like to take.

Screenshot 2022-07-03 at 16 47 30

Proposed Solution

Investigate how to override the intrinsicContentSize of the NativePicker, so that AutoLayout knows what size the picker should have.

Allow customizing font for picker

Overview

On iOS and iPadOS, it should be possible to customize the font of items displayed in the picker. The same font should also be applied to the manual input field, for consistency.

Proposed Solution

We could make use of this delegate method, instead of the limited one we're using in NativePicker.Coordinator right now.

Support more complicated value formatters

Overview

Currently, the only way to format values displayed in the picker is by overriding the label property of the ComboPickerModel implementation. This doesn't allow further customization, such as using additional context when formatting.

Proposed Solution

Add a new property that allows clients to inject a value formatter. This formatter is a generic protocol that must accept values of the ComboPickerModel implementation and return strings.

This won't be applied to macOS, where the LosslessStringConvertible must be used instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.