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
centerImage
is 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
coder
The 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
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.