The checkbox component is comprised of a box and label. If there is a group of checkboxes, a group label can be added.
The checkbox specifications on Zeroheight is here.
Checkboxes are available both in UIKit and SwiftUI. For standalone usage there are CheckboxUIView
and CheckboxView
. For group usage - CheckboxUIGroupView
and CheckboxGroupView
.
The SwiftUI component of the checkbox.
Checkbox has customizable parameters in initialization:
text
: The checkbox text.checkedImage: Image
: The tick-checkbox image for checked-state.alignment
: Positions the checkbox on the leading or trailing edge of the view.theme
: The current Spark-Theme. You always can define your own theme.intent
: The current intent of component..main
by default.isEnabled
: The parameter describes whether the checkbox is enabled or disabled.true
by default.selectionState
:CheckboxSelectionState
is either selected, unselected or indeterminate.
The UIKit component of the checkbox.
Checkbox has customizable parameters in initialization:
theme
: The current Spark-Theme. You always can define your own theme.intent
: The current intent of component..main
by default.text: String
: The checkbox text.attributedText: NSAttributedString
. An alternative attributed text to the plain text label of the checkbox.checkedImage: UIImage
: The tick-checkbox image for checked-state.isEnabled: Bool
: The control state describes whether the checkbox is enabled or disabled.true
by default.selectionState: CheckboxSelectionState
:CheckboxSelectionState
is either selected, unselected or indeterminate.alignment: CheckboxAlignment
: Positions the checkbox on the leading or trailing edge of the view.
delegate: CheckboxUIViewDelegate
? An optional delegate which may be set to be notified of changes to the checkbox. The delegate may be used as an alternative to the publisher to be informed of state changes.publisher: some Publisher<CheckboxSelectionState, Never>
All state changes to the checkbox will be published to the publisher. The publisher is an alternative to the delegate to be informed of state changes.text: String?
The label displayed to the checkbox.attributedText: NSAttributedString?
As an alternative to the text, an attributed text may be used for the labelcheckedImage: UIImage
: The tick-checkbox image for checked-state.selectionState: CheckboxSelectionState
. The current selection state of the checkbox.theme: Theme
. The current theme.intent
: The current intent.alignment: CheckboxAlignment
: Positions the checkbox on the leading or trailing edge of the view.isEnabled: Bool
. The control state of the checkbox (e.g.true
orfalse
).
A SwiftUI implementation of the check box group
Group view has the following parameters:
title
: An optional group title displayed on top of the checkbox group.checkedImage: Image
: The tick-checkbox image for checked-state.items
: An array containing of multipleCheckboxGroupItemProtocol
. Each array item is used to render a single checkbox.layout
: The layout of the group can be horizontal or vertical.alignment
: The checkbox is positioned on the leading or trailing edge of the view.theme
: The Spark-Theme. You always can define your own theme.intent
: The current intent of component..main
by default.accessibilityIdentifierPrefix
: All checkbox-views are prefixed by this identifier followed by theCheckboxGroupItemProtocol
-identifier.
A UIKit implementation of the check box group.
Group view has the following parameters:
title
: An optional group title displayed on top of the checkbox group.checkedImage: UIImage
: The tick-checkbox image for checked-state.items
: An array containing of multipleCheckboxGroupItemProtocol
. Each array item is used to render a single checkbox.layout
: The layout of the group can be horizontal or vertical.alignment
: The checkbox is positioned on the leading or trailing edge of the view.theme
: The Spark-Theme. You always can define your own theme.intent
: The current intent of component..main
by default.accessibilityIdentifierPrefix
: All checkbox-views are prefixed by this identifier followed by theCheckboxGroupItemProtocol
-identifier.
delegate: CheckboxGroupUIViewDelegate?
An optional delegate CheckboxGroupUIViewDelegate` which may be set to retrieve changes to the checkboxes. A delegate may be used instead of the publisher.publisher: some Publisher<[any CheckboxGroupItemProtocol], Never>
. Changes to the checkbox group are published to the publisher. As an alternative to subscribing to the published changes, a delegate may be used.title: String?
. An optional title of the checkbox group displayed on top of the group.checkedImage: UIImage
: The tick-checkbox image for checked-state.layout: CheckboxGroupLayout
. The layout of the checkboxalignment: CheckboxAlignment
. The checkbox is positioned on the leading or trailing edge of the view.intent:
The current intent.
private var items: [any CheckboxGroupItemProtocol] = [
CheckboxGroupItemDefault(title: Self.multilineText, id: "1", selectionState: .selected, isEnabled: false),
CheckboxGroupItemDefault(title: Self.multilineText, id: "2", selectionState: .unselected, isEnabled: true),
CheckboxGroupItemDefault(attributedTitle: Self.attributeText, id: "3", selectionState: .indeterminate, isEnabled: true)
]
let groupView = CheckboxGroupUIView(
checkedImage: checkedImage,
items: self.items,
layout: .vertical,
alignment: .left,
theme: theme,
intent: .main,
accessibilityIdentifierPrefix: "abc"
)
view.addSubview(groupView)
groupView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
groupView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
groupView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
groupView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
groupView.publisher.sink { [weak self] changedItems in
// ...
}
.store(in: &self.subscriptions)
CheckboxGroupUIViewDelegate
func checkboxGroup(_ checkboxGroup: SparkCheckbox.CheckboxGroupUIView, didChangeSelection states: [any SparkCheckbox.CheckboxGroupItemProtocol]) {
states.enumerated().forEach { index, state in
switch state.selectionState {
case .selected:
break
case .indeterminate:
break
case .unselected:
break
}
}
}
let position: CheckboxPosition
@State private var items: [any CheckboxGroupItemProtocol] = [
CheckboxGroupItemDefault(title: Self.multilineText, id: "1", selectionState: .selected, isEnabled: false),
CheckboxGroupItemDefault(title: Self.multilineText, id: "2", selectionState: .unselected, isEnabled: true),
CheckboxGroupItemDefault(attributedTitle: Self.attributeText, id: "3", selectionState: .indeterminate, isEnabled: true)
]
@State private var isEnabled: CheckboxSelectionState = CheckboxSelectionState.selected
let checkedImage = UIImage(systemName: "checkmark")!.withRenderingMode(.alwaysTemplate)
var body: some View {
CheckboxGroupView(
checkedImage: checkedImage,
items: $items,
layout: .vertical,
alignment: .left,
theme: self.theme,
intent: .main,
accessibilityIdentifierPrefix: "group"
)
.disabled(self.isEnabled == .unselected)
}
private var checkBoxSelectionState: CheckboxSelectionState = .unselected
let checkedImage = UIImage(systemName: "checkmark")!.withRenderingMode(.alwaysTemplate)
let checkbox = CheckboxUIView(
theme: theme,
intent: .main,
text: "Test",
checkedImage: checkedImage,
isEnabled: true,
selectionState: self.checkBoxSelectionState ,
alignment: .left
)
checkbox.accessibilityIdentifier = "abcCheckbox"
checkbox.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(checkbox)
checkbox.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
checkbox.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
checkbox.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
checkbox.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
checkbox.publisher.sink { [weak self] changeState in
// ...
}
.store(in: &self.subscriptions)
CheckboxUIViewDelegate
func checkbox(_ checkbox: CheckboxUIView, didChangeSelection state: CheckboxSelectionState) {
switch state.selectionState {
case .selected:
break
case .indeterminate:
break
case .unselected:
break
}
}
@State private var selection: CheckboxSelectionState = .selected
var body: some View {
VStack {
Text("Lorem Ipsum is dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard")
CheckboxView(
text: "Do you agree?",
checkedImage: checkedImage,
alignment: .left,
theme: self.theme,
intent: .main,
selectionState: $selection
)
.disabled(self.isEnabled == .unselected)
}
// HStack Usage (There might be improvment here to get rid of .fixedSize() modifier)
HStack {
Text("Lorem Ipsum is dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard")
CheckboxView(
text: "Do you agree?",
checkedImage: checkedImage,
alignment: .left,
theme: self.theme,
intent: .main,
selectionState: $selection
)
.disabled(self.isEnabled == .unselected)
.fixedSize(horizontal: false, vertical: true)
}
}
MIT License
Copyright (c) 2024 Adevinta
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.