RVS_Spinner

@IBDesignable
public class RVS_Spinner : UIControl, UIPickerViewDelegate, UIPickerViewDataSource

This is a spinner control, which acts a bit like a circular UIPickerView.

However, instead of having the values provided by a delegate/datasource, the values are associated directly with the control in an Array.

This control has a lot of little things to make it usable and intuitive. It has inertia, where you can start it spinning, it has one-tap increment/decrement, and it has haptic and audio feedback.

It can switch between the circular spinner, and a standard UIPickerView, if there are too many items to handle efficiently in a spinner. You can choose to either always use the picker, or never use the picker.

There is a delegate protocol, and the control will also emit valueChanged messages (the selected item changed), and touchUpInside messages (the center was tapped).

  • This is an optional delegate object that can be informed of selected values.

    This cannot be made inspectable, because the delegate class is not one that can be accessed as ObjC.

    Declaration

    Swift

    public weak var delegate: RVS_SpinnerDelegate?
  • This property can be overridden. It returns a UIBezierPath that defines the shape of the center.

    Declaration

    Swift

    public var centerShape: UIBezierPath { get }
  • This is the display font that we’ll use in the picker. Default is system bold 20. It can be overridden.

    Declaration

    Swift

    public var displayFont: UIFont! { get set }
  • This is the selected index of the value Array. It is 0-based.

    Declaration

    Swift

    public var selectedIndex: Int { get set }
  • This property represents the values to be selected and displayed by the spinner. Instead of a datasource, we use an instance property. This can be overloaded to make it dynamic. At minimum, each value needs an icon to be displayed. Optionally, it can have a title String, a description String, with more information, and abritrary associated data. The associated data is an Any? item. It can be anything (or nothing). It is up to the implementor to cast and manage this. This is just a context hook. The order is not changed by the spinner. Values are displayed in the order they are set in this Array, clockwise.

    Declaration

    Swift

    public var values: [RVS_SpinnerDataItem] { get set }
  • If this is true, then the spinner is open. Setting this will open or close the control. Default is false.

    Declaration

    Swift

    public var isOpen: Bool { get set }
  • If this is true, then center of the spinner will rotate against any rotation applied to its container, making it straight up. Default is true.

    Declaration

    Swift

    public var isCompensatingForContainerRotation: Bool { get set }
  • This calculated property will return either the currently selected item, or nil. READ-ONLY

    Declaration

    Swift

    public var value: RVS_SpinnerDataItem? { get }
  • If we have either a border color (tint), or a background color, then we display the icons enclosed in a frame. If that is the case, then the icon is displayed slightly smaller. READ-ONLY

    Declaration

    Swift

    public var framedIcons: Bool { get }

    Return Value

    True, if the images should be framed.

  • Declaration

    Swift

    public var opensAsSpinner: Bool { get }

    Return Value

    True, if the control will open as a spinner (as opposed to a picker). READ-ONLY

  • Declaration

    Swift

    public var count: Int { get }

    Return Value

    The number of values. READ-ONLY

  • Declaration

    Swift

    public var isEmpty: Bool { get }

    Return Value

    Yes, we have no bananas. READ-ONLY

  • This is just a convenient way to denote the spinner modes.

    See more

    Declaration

    Swift

    public enum SpinnerMode : Int
  • This is the background color associated with the closed control. We use the UIView’s backgroundColor as the source.

    This is set from the view background color.

    Declaration

    Swift

    public override var backgroundColor: UIColor? { get set }
  • This is the tint color , which governs the display of the border, and of text in the picker.

    This is set from the view background color.

    Declaration

    Swift

    public override var tintColor: UIColor! { get set }
  • This is the background color associated with the open control pie-slices. Default is nil (clear).

    Declaration

    Swift

    @IBInspectable
    public var openBackgroundColor: UIColor! { get set }
  • This is the spinner mode. It determines which control is displayed when the spinner is open.

    • both (default) is 0 The spinnerThreshold is used to determine which will be displayed.
    • radial spinner only is -1
    • picker only is 1

    Declaration

    Swift

    @IBInspectable
    public var spinnerMode: Int { get set }
  • This is the maximum number of elements that can be displayed in a spinner. Above this, needs to be displayed in a picker. Default is 15.

    Declaration

    Swift

    @IBInspectable
    public var spinnerThreshold: Int { get set }
  • If true, the control will play sounds. Default is true.

    Declaration

    Swift

    @IBInspectable
    public var isSoundOn: Bool
  • If true, the control will play haptics (on devices that support haptics). Default is true.

    Declaration

    Swift

    @IBInspectable
    public var isHapticsOn: Bool
  • This is called when the control is about to be drawn.

    Declaration

    Swift

    override public func draw(_ inRect: CGRect)

    Parameters

    inRect

    The rect to be drawn into.

  • This is required for a designable.

    Declaration

    Swift

    override public init(frame inRect: CGRect)

    Parameters

    frame

    The new frame for the view.

  • This is called when we start tracking a pan.

    Declaration

    Swift

    override public func beginTracking(_ inTouch: UITouch, with inEvent: UIEvent?) -> Bool

    Parameters

    inTouch

    The touch object associated with this event.

    with

    The event that triggered this.

  • This is called repeatedly while we are tracking a pan. We just make sure that we keep updating the display.

    Declaration

    Swift

    override public func continueTracking(_ inTouch: UITouch, with inEvent: UIEvent?) -> Bool

    Parameters

    inTouch

    The touch object associated with this event.

    with

    The event that triggered this.

  • We end the tracking, and make sure that we update the display properly.

    Declaration

    Swift

    override public func endTracking(_ inTouch: UITouch?, with inEvent: UIEvent?)

    Parameters

    inTouch

    The touch object associated with this event.

    with

    The event that triggered this.

  • We cancel the tracking, and make sure that we update the display.

    Declaration

    Swift

    override public func cancelTracking(with inEvent: UIEvent?)

    Parameters

    with

    The event that triggered this.

  • This is called before the subviews (aren’t any) will get laid out. We use it to switch out the background color. We use the set background color as the closed control background color. We use the tint color as the border color.

    Declaration

    Swift

    override public func layoutSubviews()
  • A convenience init with a preset values array and value.

    Declaration

    Swift

    public convenience init(values inValuesArray: [RVS_SpinnerDataItem]? = nil, selectedIndex inSelectedIndex: Int = 0, frame inFrame: CGRect = CGRect.zero, spinnerMode inSpinnerMode: SpinnerMode = .both, delegate inDelegate: RVS_SpinnerDelegate? = nil)

    Parameters

    values

    The values to be associated with the control. It is optional, and default is nil.

    selectedIndex

    An initial selected index for the control. It is 0-based, and optional. Default is 0.

    frame

    Any initial frame for the control. It is optional, and default is an empty frame.

    spinnerMode

    An integer, eith -1 (Spinner only), 0 (Both), or 1 (Picker only). It is optional, and default is 0 (Both).

    delegate

    A delegate instance for the spinner. It is optional, and default is nil.

  • A convenience quiet init.

    Declaration

    Swift

    public convenience init()
  • Simple number of components response (always 1)

    Declaration

    Swift

    public func numberOfComponents(in inPickerView: UIPickerView) -> Int

    Parameters

    in

    The UIPickerView doing the querying.

  • This returns how many rows will be displayed by the pickerview.

    Declaration

    Swift

    public func pickerView(_ inPickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int

    Parameters

    inPickerView

    The pickerview doing the querying.

    numberOfRowsInComponent

    The 0-based index (always 0, and ignored) of the component we are asking after.

  • Declaration

    Swift

    public func pickerView(_ inPickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat

    Parameters

    inPickerView

    The pickerview doing the querying.

    rowHeightForComponent

    The 0-based index (always 0, and ignored) of the component we are asking after.

    Return Value

    float, with the row height for that component.

  • This builds one row view, including the icon and the text. It will center them over the center of the Spinner.

    Declaration

    Swift

    public func pickerView(_ inPickerView: UIPickerView, viewForRow inRow: Int, forComponent inComponent: Int, reusing inView: UIView?) -> UIView

    Parameters

    inPickerView

    The pickerview doing the querying.

    viewForRow

    the 0-based index of the row (used to index our values).

    forComponent

    The 0-based index (always 0, and ignored) of the component we are asking after.

    reusing

    The view object to reuse.

    Return Value

    a new (or refurbed) view object.

  • This is called when a row is selected in the picker.

    Declaration

    Swift

    public func pickerView(_ inPickerView: UIPickerView, didSelectRow inRow: Int, inComponent: Int)

    Parameters

    inPickerView

    The pickerview doing the querying.

    didSelectRow

    the 0-based index of the row (used to index our values).

    inComponent

    The 0-based index (always 0, and ignored) of the component we are asking after.