A better SwiftUI Picker Use _Picker instead of Picker

Overview

BetterPicker

A better SwiftUI Picker. Use _Picker instead of Picker. Create styles with _PickerStyle.

The is a WIP

This library is currently a work-in-progress with regards to ironing out the API & documentation. Once both are in a good state a release will be cut. Until then you can point to main and deal with an unstable interface! Bug reports, testing, ideas, pull requests, and more are welcome!

Examples

You can find examples in the BetterPickerExamples App Playground.

some View { Style(configuration: configuration) } struct Style: View { let configuration: Configuration @Environment(\.isEnabled) private var isEnabled var body: some View { HStack(alignment: .selection) { Image(systemName: "arrow.right") .symbolVariant(.circle.fill) .symbolRenderingMode(.hierarchical) .selectionGuide() .foregroundColor(.accentColor) VStack(alignment: .leading) { configuration.content { view, tag in .init(makeOption(view, tag)) } } } .foregroundColor(isEnabled ? .primary : .accentColor) } @ViewBuilder func makeOption( _ option: Configuration.Option, _ tag: _Tag ) -> some View { switch tag { case let .tagged(tag): option .selectionGuide(tag == configuration.selection ? .selection : .center) .onTapGesture { withAnimation { configuration.selection = tag } } case .untagged: option } } } } extension VerticalAlignment { private enum SelectionAlignment : AlignmentID { static func defaultValue(in d: ViewDimensions) -> CGFloat { return d[.bottom] } } static let selection = VerticalAlignment(SelectionAlignment.self) } extension View { func selectionGuide(_ guide: VerticalAlignment = .selection) -> some View { alignmentGuide( guide, computeValue: { d in d[VerticalAlignment.center] } ) } }">
import SwiftUI
import BetterPicker

struct ContentView: View {
  enum DayOfWeek: String, CaseIterable {
    case monday, tuesday, wednesday, thursday, friday, saturday, sunday
    var title: String { rawValue.localizedCapitalized }
  }

  @State
  private var selection = DayOfWeek.tuesday

  @State
  private var isEnabled = true

  var body: some View {
    NavigationView {
      VStack(spacing: 15) {
        Spacer()
        _Picker("Testing", selection: $selection) {
          ForEach(DayOfWeek.allCases, id: \.self) {
            Text($0.title).tag($0)
          }
          Text("Not a real option.")
        }
        .pickerStyle(.arrow)
        .disabled(!isEnabled)
        .font(.largeTitle)
        Spacer()
        Button("Toggle Disabled") {
          isEnabled.toggle()
        }
        .buttonStyle(.bordered)
        .padding()
      }
      .navigationTitle(selection.title)
    }
    .navigationViewStyle(.stack)
  }
}

extension _PickerStyle where Self == ArrowStyle {
  static var arrow: ArrowStyle { .init() }
}

struct ArrowStyle: _PickerStyle {
  func makeBody(configuration: Configuration) -> some View {
    Style(configuration: configuration)
  }

  struct Style: View {
    let configuration: Configuration

    @Environment(\.isEnabled)
    private var isEnabled

    var body: some View {
      HStack(alignment: .selection) {
        Image(systemName: "arrow.right")
          .symbolVariant(.circle.fill)
          .symbolRenderingMode(.hierarchical)
          .selectionGuide()
          .foregroundColor(.accentColor)
        VStack(alignment: .leading) {
          configuration.content { view, tag in
              .init(makeOption(view, tag))
          }
        }
      }
      .foregroundColor(isEnabled ? .primary : .accentColor)
    }

    @ViewBuilder
    func makeOption(
      _ option: Configuration.Option,
      _ tag: _Tag
    ) -> some View {
      switch tag {
      case let .tagged(tag):
        option
          .selectionGuide(tag == configuration.selection ? .selection : .center)
          .onTapGesture {
            withAnimation {
              configuration.selection = tag
            }
          }
      case .untagged:
        option
      }
    }
  }
}

extension VerticalAlignment {
  private enum SelectionAlignment : AlignmentID {
    static func defaultValue(in d: ViewDimensions) -> CGFloat {
      return d[.bottom]
    }
  }
  static let selection = VerticalAlignment(SelectionAlignment.self)
}

extension View {
  func selectionGuide(_ guide: VerticalAlignment = .selection) -> some View {
    alignmentGuide(
      guide,
      computeValue: { d in d[VerticalAlignment.center] }
    )
  }
}
You might also like...
A country picker view controller for iOS
A country picker view controller for iOS

Planet A country picker view controller for iOS. Installation CocoaPods You can use CocoaPods to install Planet by adding it to your Podfile: platform

MICountryPicker is a country picker controller for iOS8+ with an option to search.
MICountryPicker is a country picker controller for iOS8+ with an option to search.

MICountryPicker MICountryPicker is a country picker controller for iOS8+ with an option to search. The list of countries is based on the ISO 3166 coun

A simple, customizable Country picker for picking country or dialing code. 🇮🇳 🇯🇵 🇰🇷 🇩🇪 🇨🇳 🇺🇸 🇫🇷 🇪🇸 🇮🇹 🇷🇺 🇬🇧
A drop in single image picker.

PHSingleImagePicker A low memory, single image picker wrapper that provide a significant smaller file size while also preserve high image quality. Int

A simple yet customizable horizontal and vertical picker view
A simple yet customizable horizontal and vertical picker view

WheelPicker A simple yet customizable horizontal and vertical picker view Features Vertical or Horizontal picker Image or Text data Configure UILabel

React-native-place-picker: Pick any place with single click 🚀
React-native-place-picker: Pick any place with single click 🚀

React-native-place-picker: Pick any place with single click 🚀

 🤯 PickEmoji: A SwiftUI Extension to Pick the Emojis that you wish
🤯 PickEmoji: A SwiftUI Extension to Pick the Emojis that you wish

🤯 PickEmoji: A SwiftUI Extension to Pick the Emojis that you wish You can use this library in your projects 🙃 . You can search the emojis too. Below

A replacement for as which runs in constant time instead of O(n) when the conformance is not satisfiedA replacement for as which runs in constant time instead of O(n) when the conformance is not satisfied

ZConform A replacement for as? which runs in constant time instead of O(n) when the conformance is not satisfied. How it works ZConform does a one-tim

This provides a bridge to use Sync with Tokamak instead of SwiftUI
This provides a bridge to use Sync with Tokamak instead of SwiftUI

Sync Tokamak This provides a bridge to use Sync with Tokamak instead of SwiftUI.

HockeyKit - HockeyApp was retired and the SDKs are deprecated. Please use App Center instead.

About: Hockey is a iOS Ad-Hoc updater framework. It can be used for all apps that target the Apple AppStore and improves the beta testing process dram

Better time picker for iOS.

TimePicker Better TimePicker for iOS Requirements Swift 5.0 iOS 10.0+ Xcode 10.2+ Installation The easiest way is through CocoaPods. Simply add the de

Better time picker for iOS.

TimePicker Better TimePicker for iOS Requirements Swift 5.0 iOS 10.0+ Xcode 10.2+ Installation The easiest way is through CocoaPods. Simply add the de

A customizable, full-feature, lightweight iOS framework to be used instead of UIAlertController.
A customizable, full-feature, lightweight iOS framework to be used instead of UIAlertController.

A customizable, full-feature, lightweight iOS framework to be used instead of UIAlertController.

An easy way to access reviews for your app instead of writing repetitive and redundant codes for every app.

AppStoreReviewManager An easy way to access reviews for your app instead of writing repetitive and redundant codes for every app. Requirements iOS 9.0

Create macOS apps with Swift packages instead of Xcode projects

Swift Bundler A Swift Package Manager wrapper that allows the creation of MacOS apps with Swift packages instead of Xcode projects. My motivation is t

KYWheelTabController is a subclass of UITabBarController.It displays the circular menu instead of UITabBar.
KYWheelTabController is a subclass of UITabBarController.It displays the circular menu instead of UITabBar.

KYWheelTabController KYWheelTabController is a subclass of UITabBarController.It displays the circular menu instead of UITabBar. Installation CocoaPod

This iOS framework allows settings to be in-app in addition to or instead of being in the Settings app.
This iOS framework allows settings to be in-app in addition to or instead of being in the Settings app.

InAppSettingsKit InAppSettingsKit (IASK) is an open source framework to easily add in-app settings to your iOS or Catalyst apps. Normally iOS apps use

An Integer type that clamps its value to its minimum and maximum instead of over- or underflowing.

ClampedInteger An Integer type that clamps its value to its minimum and maximum instead of over- or underflowing. Examples let big = ClampedIntege

React Native utility library around image and video files for getting metadata like MIME type, timestamp, duration, and dimensions. Works on iOS and Android using Java and Obj-C, instead of Node 🚀.

Qeepsake React Native File Utils Extracts information from image and video files including MIME type, duration (video), dimensions, and timestamp. The

Comments
  • Package name and Configuration type alias issue

    Package name and Configuration type alias issue

    Hi,

    Thanks for the package. Finally I can easily style pickers. I've noticed 2 issues while using the package:

    • the package name should be BetterPicker instead of swiftui-betterpicker in the Package.swift file
    • the Configuration type alias should be public in _Picker
    opened by kuglee 0
Owner
Eric Lewis
Developer & Father. Feel free to reach out on twitter if I don't get back to you here.
Eric Lewis
Elegant and Easy-to-Use iOS Swift Date Picker

D2PDatePicker Example To run the example project, clone the repo, and run pod install from the Example directory first. Example Code: Programmatical I

Pradheep Rajendirane 292 Nov 6, 2022
LocationPicker - A ready for use and fully customizable location picker for your app

LocationPicker A ready for use and fully customizable location picker for your app. Features Installation Cocoapods Carthage Swift Package Manager Qui

Zhuoran 397 Nov 16, 2022
Multi-picker for iOS and Mac available in SwiftUI

Multi-picker for iOS and Mac available in Swift UI

1amageek 5 Jul 12, 2022
iOS/macOS media picker for importing images and videos in SwiftUI

iOS/macOS media picker for importing images and videos in SwiftUI.

Mobile Development Club 13 Dec 30, 2022
A SwiftUI implementation of a picker that also allows direct input.

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. Installatio

Alessio Moiso 5 Sep 13, 2022
FYPhoto is a photo/video picker and image browser library for iOS written in pure Swift. It is feature-rich and highly customizable to match your App's requirements.

FYPhoto is a photo/video picker and image browser library for iOS written in pure Swift. It is feature-rich and highly customizable to match your App's requirements.

null 10 Dec 11, 2022
Date picker dialog for iOS

DatePickerDialog 4.0 - iOS - Swift DatePickerDialog is an iOS drop-in classe that displays an UIDatePicker within an UIAlertView. Requirements DatePic

Squimer 535 Dec 17, 2022
a picker view shown as a popup for iOS in Objective-C

CZPicker Demo Change Log 3 most recent changes are listed here. Full change logs v0.4.3 - 2016-08-12 Added - (void)czpickerViewWillDisplay:(CZPickerVi

Chen Zeyu 527 Oct 2, 2022
🎯 Swift country and phone code Picker

CountryPicker Picker code Swift 3 / 4 / 5. Example To run the example project, clone the repo, and run pod install from the Example directory first. U

null 207 Dec 22, 2022
An iOS picker view to serve all your "picking" needs

Mandoline The PickerView is a UICollectionView that provides a smooth "picking" interface. In order to get the most out of it, a consuming view contro

Blue Apron 883 Nov 28, 2022