Merge branch 'feature/checkboxView_constraints' into 'develop'

Checkbox view constraints

See merge request BPHV_MIPS/mvm_core_ui!194
This commit is contained in:
Pan, Xinlei (Ryan) 2019-12-19 15:26:03 -05:00
commit 767ee787cb
5 changed files with 88 additions and 93 deletions

View File

@ -11,11 +11,13 @@ import MVMCore
/**
This class expects its height and width to be equal.
*/
@objcMembers open class Checkbox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol {
@objcMembers open class Checkbox: Control, MVMCoreUIViewConstrainingProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var sizeObject: MFSizeObject? = MFSizeObject(standardSize: Checkbox.defaultHeightWidth, standardiPadPortraitSize: Checkbox.defaultHeightWidth + 6.0)
// Form Validation
var isRequired = false
var fieldKey: String?
@ -117,8 +119,8 @@ import MVMCore
// MARK: - Constraints
//--------------------------------------------------
private var heightConstraint: NSLayoutConstraint?
private var widthConstraint: NSLayoutConstraint?
public var heightConstraint: NSLayoutConstraint?
public var widthConstraint: NSLayoutConstraint?
/// Updates the height and width anchors of the Checkbox with the assigned value.
public var heigthWidthConstant: CGFloat = Checkbox.defaultHeightWidth {
@ -138,7 +140,6 @@ import MVMCore
accessibilityTraits = .button
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint")
updateAccessibilityLabel()
setupView()
}
/// There is currently no intention on using xib files.
@ -147,7 +148,7 @@ import MVMCore
fatalError("xib file is not implemented for Checkbox.")
}
public convenience init() {
public convenience override init() {
self.init(frame:.zero)
}
@ -180,7 +181,8 @@ import MVMCore
layer.borderColor = borderColor.cgColor
}
open func setupView() {
open override func setupView() {
super.setupView()
guard constraints.isEmpty else { return }
@ -349,18 +351,7 @@ import MVMCore
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sendActions(for: touchIsAcceptablyOutside(touches.first) ? .touchUpOutside : .touchUpInside)
}
func touchIsAcceptablyOutside(_ touch: UITouch?) -> Bool {
let endLocation = touch?.location(in: self)
let x = endLocation?.x ?? 0.0
let y = endLocation?.y ?? 0.0
let faultTolerance: CGFloat = 20.0
let widthLimit = CGFloat(bounds.size.width + faultTolerance)
let heightLimt = CGFloat(bounds.size.height + faultTolerance)
return x < -faultTolerance || y < -faultTolerance || x > widthLimit || y > heightLimt
sendActions(for: .touchUpInside)
}
override open func accessibilityActivate() -> Bool {
@ -376,7 +367,8 @@ import MVMCore
return true
}
open func reset() {
open override func reset() {
super.reset()
isEnabled(true)
shapeLayer?.removeAllAnimations()
@ -396,17 +388,24 @@ import MVMCore
setupView()
}
public func updateView(_ size: CGFloat) {
public override func updateView(_ size: CGFloat) {
super.updateView(size)
if let dimension = sizeObject?.getValueBased(onSize: size) {
widthConstraint?.constant = dimension
heightConstraint?.constant = dimension
}
layoutIfNeeded()
}
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
self.delegateObject = delegateObject
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
guard let dictionary = json else { return }
groupName = dictionary.optionalStringForKey("groupName")
fieldValue = dictionary.optionalStringForKey("value")
if let fieldKey = dictionary[KeyFieldKey] as? String {
@ -463,7 +462,7 @@ import MVMCore
// MARK:- FormValidationProtocol
extension Checkbox: FormValidationFormFieldProtocol {
public func formFieldGroupName() -> String? {
return groupName
}

View File

@ -7,7 +7,7 @@
//
@objcMembers open class CheckboxWithLabelView: ViewConstrainingView {
@objcMembers open class CheckboxWithLabelView: View {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
@ -19,9 +19,7 @@
// MARK: - Properties
//--------------------------------------------------
var sizeObject: MFSizeObject? = MFSizeObject(standardSize: Checkbox.defaultHeightWidth, standardiPadPortraitSize: Checkbox.defaultHeightWidth + 6.0)
var checkboxPosition: CheckboxPosition = .center
public var checkboxPosition: CheckboxPosition = .center
public enum CheckboxPosition: String {
case center
@ -32,13 +30,10 @@
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
var checkboxWidthConstraint: NSLayoutConstraint?
var checkboxHeightConstraint: NSLayoutConstraint?
var checkboxTopConstraint: NSLayoutConstraint?
var checkboxBottomConstraint: NSLayoutConstraint?
var checkboxCenterYConstraint: NSLayoutConstraint?
var centerLabelCheckboxConstraint: NSLayoutConstraint?
public var checkboxTopConstraint: NSLayoutConstraint?
public var checkboxBottomConstraint: NSLayoutConstraint?
public var checkboxCenterYConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Life Cycle
@ -49,32 +44,20 @@
guard subviews.isEmpty else { return }
translatesAutoresizingMaskIntoConstraints = false
addSubview(checkbox)
addSubview(label)
label.text = ""
let dimension = sizeObject?.getValueBasedOnApplicationWidth() ?? Checkbox.defaultHeightWidth
checkboxWidthConstraint = checkbox.heightAnchor.constraint(equalToConstant: dimension)
checkboxWidthConstraint?.isActive = true
checkboxHeightConstraint = checkbox.widthAnchor.constraint(equalToConstant: dimension)
checkboxHeightConstraint?.isActive = true
checkbox.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
checkbox.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: checkbox.bottomAnchor).isActive = true
let checboxBottom = checkbox.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor)
checboxBottom.priority = UILayoutPriority(249)
checboxBottom.isActive = true
// Allows various positions of checkbox.
checkboxBottomConstraint = layoutMarginsGuide.bottomAnchor.constraint(equalTo: checkbox.bottomAnchor)
checkboxBottomConstraint?.isActive = true
checkboxTopConstraint = checkbox.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor)
checkboxTopConstraint?.isActive = true
checkboxCenterYConstraint = checkbox.centerYAnchor.constraint(equalTo: centerYAnchor)
centerLabelCheckboxConstraint = label.centerYAnchor.constraint(equalTo: checkbox.centerYAnchor)
label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
layoutMarginsGuide.trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true
@ -82,7 +65,7 @@
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true
let bottomLabelConstraint = layoutMarginsGuide.bottomAnchor.constraint(equalTo: label.bottomAnchor)
bottomLabelConstraint.priority = UILayoutPriority(249)
bottomLabelConstraint.priority = .defaultLow
bottomLabelConstraint.isActive = true
alignCheckbox(.center)
@ -92,17 +75,12 @@
// MARK: - Initializers
//--------------------------------------------------
required public init?(coder: NSCoder) {
super.init(coder: coder)
fatalError("xib file is not implemented for CheckboxWithLabelView")
}
override public init(frame: CGRect) {
public override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
public convenience init() {
public convenience override init() {
self.init(frame: .zero)
}
@ -112,6 +90,11 @@
alignCheckbox(position)
}
required public init?(coder: NSCoder) {
super.init(coder: coder)
fatalError("xib file is not implemented for CheckboxWithLabelView")
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
@ -125,64 +108,41 @@
checkboxBottomConstraint?.isActive = false
checkboxTopConstraint?.isActive = false
checkboxCenterYConstraint?.isActive = true
centerLabelCheckboxConstraint?.isActive = true
case .top:
checkboxBottomConstraint?.isActive = false
checkboxTopConstraint?.isActive = true
checkboxCenterYConstraint?.isActive = false
centerLabelCheckboxConstraint?.isActive = false
case .bottom:
checkboxBottomConstraint?.isActive = true
checkboxTopConstraint?.isActive = false
checkboxCenterYConstraint?.isActive = false
centerLabelCheckboxConstraint?.isActive = false
}
}
}
/// MARK: - Molecular
// MARK: - Molecular
extension CheckboxWithLabelView {
override open class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return CGFloat(Checkbox.defaultHeightWidth)
open class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 200
}
@objc override open func updateView(_ size: CGFloat) {
super.updateView(size)
label.updateView(size)
if self.checkbox.responds(to: #selector(self.updateView(_:))) {
if let dimension = sizeObject?.getValueBased(onSize: size) {
checkboxWidthConstraint?.constant = dimension
checkboxHeightConstraint?.constant = dimension
checkbox.updateView(size)
}
}
checkbox.updateView(size)
layoutIfNeeded()
}
override open func horizontalAlignment() -> UIStackView.Alignment {
return .leading
}
open override func resetConstraints() {
super.resetConstraints()
checkboxCenterYConstraint?.isActive = false
checkboxBottomConstraint?.isActive = false
checkboxTopConstraint?.isActive = false
centerLabelCheckboxConstraint?.isActive = false
}
open override func reset() {
super.reset()
label.text = ""
checkbox.reset()
alignCheckbox(.center)
}
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {

View File

@ -8,37 +8,64 @@
import UIKit
public class Control: UIControl {
var json: [AnyHashable: Any]?
@objcMembers open class Control: UIControl {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var json: [AnyHashable: Any]?
private var initialSetupPerformed = false
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public override init(frame: CGRect) {
super.init(frame: .zero)
initialSetup()
}
init() {
public init() {
super.init(frame: .zero)
initialSetup()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
fatalError("Control does not support xib.")
}
//--------------------------------------------------
// MARK: - Setup
//--------------------------------------------------
public func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
setupView()
}
}
//--------------------------------------------------
// MARK: - UITouch
//--------------------------------------------------
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
// If the control is smaller than 44pt by width or height, this will compensate.
let faultToleranceX: CGFloat = max((MinimumTappableArea - bounds.size.width) / 2.0, 0)
let faultToleranceY: CGFloat = max((MinimumTappableArea - bounds.size.height) / 2.0, 0)
let area = bounds.insetBy(dx: -faultToleranceX, dy: -faultToleranceY)
return area.contains(point)
}
}
// MARK: - MVMCoreViewProtocol
extension Control: MVMCoreViewProtocol {
public func updateView(_ size: CGFloat) {
}
public func updateView(_ size: CGFloat) {}
/// Will be called only once.
public func setupView() {
@ -47,8 +74,9 @@ extension Control: MVMCoreViewProtocol {
}
}
// MARK: - MVMCoreUIMoleculeViewProtocol
extension Control: MVMCoreUIMoleculeViewProtocol {
public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
self.json = json
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {

View File

@ -77,3 +77,7 @@ typedef NS_ENUM(NSInteger, CoreUIErrorCode) {
ErrorCodeModuleMolecule = 100,
ErrorCodeListMolecule = 101
};
#pragma mark - Apple Design Guidelines
extern CGFloat const MinimumTappableArea;

View File

@ -69,3 +69,7 @@ BOOL DisableAnimations = NO;
// Hand Scroll Key
NSString * const KeyHandScrollAnimation = @"handScrollAnimation";
NSString * const KeyHandScroll = @"hand_scroll";
#pragma mark - Apple Design Guidelines
CGFloat const MinimumTappableArea = 44.0f;