RVS_Spinner
@available(iOS 13.0, *)
@IBDesignable
open 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 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 moreDeclaration
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 an alternative fixed center image. If left alone, the selected value image will be used. Default is nil (use selected value image).
Declaration
Swift
@IBInspectable public var centerImage: UIImage? { get set } -
If true, then the various options will be set to emulate a “HUD” display. Default is false.
Declaration
Swift
@IBInspectable public var hudMode: Bool { get set } -
If true, and an explicit image has been assigned to the center, when the cotrol is opened, the image will be replaced with the current selection. This is ignored, if
centerImageis nil. Default is false.Declaration
Swift
@IBInspectable public var replaceCenterImage: Bool { get set }
-
The NSCoder init.
Declaration
Swift
required public init?(coder inDecoder: NSCoder)Parameters
coderThe decoder with the view state.
-
This is called when the control is about to be drawn.
Declaration
Swift
override public func draw(_ inRect: CGRect)Parameters
inRectThe rect to be drawn into.
-
This is required for a designable.
Declaration
Swift
override public init(frame inRect: CGRect)Parameters
frameThe 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?) -> BoolParameters
inTouchThe touch object associated with this event.
withThe 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?) -> BoolParameters
inTouchThe touch object associated with this event.
withThe 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
inTouchThe touch object associated with this event.
withThe 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
withThe 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
valuesThe values to be associated with the control. It is optional, and default is nil.
selectedIndexAn initial selected index for the control. It is 0-based, and optional. Default is 0.
frameAny initial frame for the control. It is optional, and default is an empty frame.
spinnerModeAn integer, eith -1 (Spinner only), 0 (Both), or 1 (Picker only). It is optional, and default is 0 (Both).
delegateA 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) -> IntParameters
inThe 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) -> IntParameters
inPickerViewThe pickerview doing the querying.
numberOfRowsInComponentThe 0-based index (always 0, and ignored) of the component we are asking after.
-
Declaration
Swift
public func pickerView(_ inPickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloatParameters
inPickerViewThe pickerview doing the querying.
rowHeightForComponentThe 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?) -> UIViewParameters
inPickerViewThe pickerview doing the querying.
viewForRowthe 0-based index of the row (used to index our values).
forComponentThe 0-based index (always 0, and ignored) of the component we are asking after.
reusingThe 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
inPickerViewThe pickerview doing the querying.
didSelectRowthe 0-based index of the row (used to index our values).
inComponentThe 0-based index (always 0, and ignored) of the component we are asking after.
View on GitHub