Further checkbox setups.

This commit is contained in:
Kevin G Christiano 2019-09-16 09:50:35 -04:00
parent 8238a42177
commit bbdb0301eb
3 changed files with 317 additions and 71 deletions

View File

@ -8,14 +8,18 @@
import MVMCore import MVMCore
class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol { class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
var lineWidth: CGFloat = 0.0
var lineColor: UIColor?
private var _lineColor: UIColor = .black
private var _lineWidth: CGFloat = 1.0
private var drawPercentage: Float = 0.0
private var animationTimer: Timer?
private var checkLayer: CAShapeLayer?
let startXOffset: Float = 42.0 / 124.0 let startXOffset: Float = 42.0 / 124.0
let startYOffset: Float = 66.0 / 124.0 let startYOffset: Float = 66.0 / 124.0
@ -24,7 +28,7 @@ class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, M
let endXOffset: Float = 83.0 / 124.0 let endXOffset: Float = 83.0 / 124.0
let endYOffset: Float = 46.0 / 124.0 let endYOffset: Float = 46.0 / 124.0
let pivotPercentage: Float = 0.34 let pivotPercentage: Float = 0.34
let endPercentage = 1.0 - pivotPercentage let endPercentage = 0.66
let animationInterval: Float = 0.01 let animationInterval: Float = 0.01
@ -32,63 +36,73 @@ class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, M
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
private var drawPercentage: Float = 0.0 override init(frame: CGRect) {
private var animationTimer: Timer? super.init(frame: frame)
private var checkLayer: CAShapeLayer?
private var selected = false
func setupView() { backgroundColor = .clear
super.setupView() drawPercentage = 1.0
backgroundColor = UIColor.clear lineColor = .black
drawPercentage = 1.0 lineWidth = 1.0
lineColor = UIColor.black }
lineWidth = 1.0
} required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
func update(_ size: CGFloat) { fatalError("Xib File is not implemented for CheckBox.")
super.update(size) }
}
var lineWidth: CGFloat { var lineWidth: CGFloat {
get { get {
return super.lineWidth return _lineWidth
} }
set(lineWidth) { set(lineWidth) {
self.lineWidth = lineWidth self.lineWidth = lineWidth
if checkLayer { guard let checkLayer = checkLayer else { return }
checkLayer.removeFromSuperlayer() checkLayer.removeFromSuperlayer()
checkLayer = nil checkLayer = nil
updateCheckSelected(selected, animated: false) updateCheckSelected(isSelected, animated: false)
}
} }
} }
var lineColor: UIColor {
get {
return _lineColor
}
set(lineColor) {
_lineColor = lineColor
if let checkLayer = checkLayer {
checkLayer.strokeColor = lineColor.cgColor
updateCheckSelected(isSelected, animated: false)
}
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Draw // MARK: - Draw
//-------------------------------------------------- //--------------------------------------------------
func drawCheck() { func drawCheck() {
if !checkLayer {
layoutIfNeeded() guard let checkLayer = checkLayer else { return }
let path = UIBezierPath()
path.move(to: CGPoint(x: lineWidth / 2, y: bounds.size.height * 0.55)) layoutIfNeeded()
path.addLine(to: CGPoint(x: bounds.size.width * 0.45, y: bounds.size.height * 0.85)) let path = UIBezierPath()
path.addLine(to: CGPoint(x: bounds.size.width - lineWidth / 2, y: lineWidth / 2)) path.move(to: CGPoint(x: lineWidth / 2, y: bounds.size.height * 0.55))
path.addLine(to: CGPoint(x: bounds.size.width * 0.45, y: bounds.size.height * 0.85))
checkLayer = CAShapeLayer() path.addLine(to: CGPoint(x: bounds.size.width - lineWidth / 2, y: lineWidth / 2))
checkLayer.frame = bounds
layer.addSublayer(checkLayer) checkLayer = CAShapeLayer()
checkLayer.strokeColor = lineColor.cgColor ?? UIColor.black.cgColor checkLayer.frame = bounds
checkLayer.fillColor = UIColor.clear.cgColor layer.addSublayer(checkLayer)
checkLayer.path = path.cgPath checkLayer.strokeColor = lineColor.cgColor
checkLayer.lineWidth = lineWidth checkLayer.fillColor = UIColor.clear.cgColor
checkLayer.path = path.cgPath
CATransaction.begin() checkLayer.lineWidth = lineWidth
CATransaction.setDisableActions(true)
checkLayer.strokeEnd = 0.0 CATransaction.begin()
CATransaction.commit() CATransaction.setDisableActions(true)
} checkLayer.strokeEnd = 0.0
CATransaction.commit()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -96,15 +110,17 @@ class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, M
//-------------------------------------------------- //--------------------------------------------------
func updateCheckSelected(_ selected: Bool, animated: Bool) { func updateCheckSelected(_ selected: Bool, animated: Bool) {
MVMCoreDispatchUtility.performBlock(onMainThread: {
self.selected = selected DispatchQueue.main.async {
self.isSelected = selected
// animate this bar // animate this bar
self.drawCheck() self.drawCheck()
var layer: CAShapeLayer? var layer: CAShapeLayer?
if self.checkLayer.presentation() != nil && animated { if self.checkLayer?.presentation() != nil && animated {
layer = self.checkLayer.presentation() layer = self.checkLayer!.presentation()
} else { } else {
layer = self.checkLayer layer = self.checkLayer
} }
@ -116,11 +132,8 @@ class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, M
animateStrokeEnd.duration = 0.3 animateStrokeEnd.duration = 0.3
animateStrokeEnd.fromValue = NSNumber(value: Float(layer?.strokeEnd ?? 0.0)) animateStrokeEnd.fromValue = NSNumber(value: Float(layer?.strokeEnd ?? 0.0))
if selected {
animateStrokeEnd.toValue = NSNumber(value: 1) animateStrokeEnd.toValue = NSNumber(value: selected ? 1 : 0)
} else {
animateStrokeEnd.toValue = NSNumber(value: 0)
}
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear) animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
layer?.add(animateStrokeEnd, forKey: "strokeEndAnimation") layer?.add(animateStrokeEnd, forKey: "strokeEndAnimation")
@ -128,38 +141,38 @@ class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, M
layer?.removeAllAnimations() layer?.removeAllAnimations()
CATransaction.begin() CATransaction.begin()
CATransaction.setDisableActions(true) CATransaction.setDisableActions(true)
if selected { layer?.strokeEnd = selected ? 1.0 : 0.0
layer?.strokeEnd = 1.0
} else {
layer?.strokeEnd = 0.0
}
CATransaction.commit() CATransaction.commit()
} }
})
}
func setLineColor(_ lineColor: UIColor?) {
self.lineColor = lineColor
if checkLayer {
checkLayer.strokeColor = lineColor?.cgColor
updateCheckSelected(selected, animated: false)
} }
} }
func layoutSubviews() { override func layoutSubviews() {
drawCheck() drawCheck()
} }
private func defaultState() {
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Molecular // MARK: - Molecular
//-------------------------------------------------- //--------------------------------------------------
open func reset() {
}
open func setAsMolecule() {
}
func updateView(_ size: CGFloat) { func updateView(_ size: CGFloat) {
<#code#>
} }
func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
<#code#>
} }
} }

View File

@ -32,6 +32,237 @@ class CheckBoxWithLabel: ViewConstrainingView {
// TODO: MVMCoreUICheckBox.m // TODO: MVMCoreUICheckBox.m
func needsToBeConstrained() -> Bool {
return true
}
func alignment() -> UIStackView.Alignment {
return .leading
}
func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
FormValidator.setupValidation(withMolecule: self, delegate: delegateObject?.formValidationProtocol)
delegate = delegateObject
fieldKey = json?.string(for: KeyFieldKey)
isRequired = json?.bool(forKey: KeyRequired)
let checkedColorHex = json?.string("checkedColor")
let unCheckedColorHex = json?.string("unCheckedColor")
let checkedColor = checkedColorHex != nil ? UIColor.mfGet(forHex: checkedColorHex) : UIColor.clear
let unCheckedColor = unCheckedColorHex != nil ? UIColor.mfGet(forHex: unCheckedColorHex) : UIColor.clear
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor, label: json?.dict(KeyLabel), delegateObject: delegateObject, additionalData: additionalData)
}
class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return CGFloat(CheckBoxHeightWidth)
}
// MARK: - convenient class methods
class func mf() -> Self {
let checkBox = self.init(frame: CGRect.zero)
checkBox.translatesAutoresizingMaskIntoConstraints = false
return checkBox
}
class func mfCheckBoxWithRoundedRect() -> Self? {
let checkBox = self.init(roundRect: true)
checkBox.translatesAutoresizingMaskIntoConstraints = false
return checkBox
}
class func mfCheckBox(withCheckedColor checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, text: String?) -> Self {
let checkBox = self.init(checkedColor: checkedColor, unCheck: unCheckedColor, text: text)
checkBox?.translatesAutoresizingMaskIntoConstraints = false
return checkBox
}
class func mfCheckBox(withCheckedColor checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, atributedText attributedText: NSAttributedString?) -> Self {
let checkBox = self.init(checkedColor: checkedColor, unCheck: unCheckedColor, attributedText: attributedText)
checkBox?.translatesAutoresizingMaskIntoConstraints = false
return checkBox
}
// MARK: - FormValidationProtocol
func isValidField() -> Bool {
if isRequired {
return isSelected()
}
return true
}
func formFieldName() -> String? {
return fieldKey
}
func formFieldValue() -> Any? {
return NSNumber(value: isSelected())
}
// MARK: - inits
init() {
super.init()
setupView()
}
init(checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, text: String?) {
super.init()
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor, text: text)
addAccessibleProperties()
}
init(checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, attributedText: NSAttributedString?) {
super.init()
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor, text: nil)
descriptionAttributedText = attributedText
addAccessibleProperties()
}
init?(checkMarkView: MVMCoreUICheckMarkView?, checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, text: String?) {
super.init()
checkMark = checkMarkView
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor, text: text)
addAccessibleProperties()
}
init?(checkMarkView: MVMCoreUICheckMarkView?, checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, attributedText: NSAttributedString?) {
super.init()
checkMark = checkMarkView
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor, text: nil)
descriptionAttributedText = attributedText
addAccessibleProperties()
}
init(roundRect isRoundRect: Bool) {
super.init()
isRoundRectCheckMark = isRoundRect
setup(withCheckedColor: UIColor.white, unCheck: UIColor.white, text: nil)
addAccessibleProperties()
setCheckMarkLayer()
}
//default inits
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
setup(withCheckedColor: UIColor.white, unCheck: UIColor.white, text: nil)
addAccessibleProperties()
}
init(frame: CGRect) {
super.init(frame: frame)
setupView()
setup(withCheckedColor: UIColor.white, unCheck: UIColor.white, text: nil)
addAccessibleProperties()
}
func awakeFromNib() {
super.awakeFromNib()
setup(withCheckedColor: UIColor.white, unCheck: UIColor.white, text: nil)
}
func setupView() {
let containterView = MVMCoreUICommonViewsUtility.commonView()
containterView?.isUserInteractionEnabled = false
if !sizeObject {
sizeObject = MFSizeObject(standardSize: CheckBoxHeightWidth, standardiPadPortraitSize: Int(CheckBoxHeightWidth) + 6)
}
//checked circle
if !self.checkedSquare {
let checkedSquare = MVMCoreUICommonViewsUtility.commonView()
checkedSquare?.backgroundColor = UIColor.white
if let checkedSquare = checkedSquare {
containterView?.addSubview(checkedSquare)
}
let size = sizeObject.getValueBasedOnApplicationWidth()
let constraints = NSLayoutConstraint.constraintPinView(checkedSquare, heightConstraint: true, heightConstant: size, widthConstraint: true, widthConstant: size)
checkboxWidth = constraints[ConstraintWidth]
checkboxHeight = constraints[ConstraintHeight]
NSLayoutConstraint.constraintPinSubview(checkedSquare, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false)
checkboxRightPinConstraint = checkedSquare?.trailingAnchor.constraintEqual(to: containterView?.trailingAnchor)
NSLayoutConstraint.constraintPinSubview(checkedSquare, pinCenterX: false, pinCenterY: true)
self.checkedSquare = checkedSquare
self.checkBoxBorder = UIColor.black
}
// TODO: OBJC CODE
//check mark
if (!self.checkMark) {
MVMCoreUICheckMarkView *checkMark = [[MVMCoreUICheckMarkView alloc] initWithFrame:self.frame];
checkMark.lineWidth = 2.0;
self.checkMark = checkMark;
self.checkMark.translatesAutoresizingMaskIntoConstraints = NO;
[self.checkedSquare addSubview:self.checkMark];
[self.checkMark.widthAnchor constraintEqualToAnchor:self.checkedSquare.widthAnchor multiplier:.4].active = YES;
[self.checkMark.heightAnchor constraintEqualToAnchor:self.checkedSquare.heightAnchor multiplier:.4].active = YES;
[self.checkMark.centerXAnchor constraintEqualToAnchor:self.checkedSquare.centerXAnchor].active = YES;
[self.checkMark.centerYAnchor constraintEqualToAnchor:self.checkedSquare.centerYAnchor].active = YES;
}
//label
if (!self.descriptionLabel) {
Label *descriptionLabel = [Label commonLabelB2:YES];
[containterView addSubview:descriptionLabel];
[NSLayoutConstraint constraintPinSubview:descriptionLabel pinCenterX:NO pinCenterY:YES];
[NSLayoutConstraint constraintPinSubview:descriptionLabel pinTop:NO pinBottom:NO pinLeft:NO pinRight:YES];
self.descriptionLabelLeadingConstraint = [NSLayoutConstraint constraintWithItem:descriptionLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.checkedSquare attribute:NSLayoutAttributeTrailing multiplier:1 constant:11];
self.descriptionLabelLeadingConstraint.active = YES;
self.descriptionLabelLeadingConstraint.active = YES;
self.descriptionLabel = descriptionLabel;
[self setSelected:NO];
}
if (!self.containerView) {
[self addSubview:containterView];
self.containerView = containterView;
[NSLayoutConstraint constraintPinSubviewToSuperview:containterView];
}
}
func setup(withCheckedColor checkedColor: UIColor?, unCheck unCheckedColor: UIColor?) {
if checkedColor != nil {
self.checkedColor = checkedColor
}
if unCheckedColor != nil {
self.unCheckedColor = unCheckedColor
}
}
func setup(withCheckedColor checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, text: String?) {
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor)
descriptionText = text ?? ""
}
func setup(withCheckedColor checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, label labelJson: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) {
setup(withCheckedColor: checkedColor, unCheck: unCheckedColor)
descriptionLabel.setWithJSON(labelJson, delegateObject: delegateObject, additionalData: additionalData)
}
@objc func updateView(_ size: CGFloat) {
MVMCoreDispatchUtility.performBlock(onMainThread: {
self.descriptionLabel.updateView(size)
if self.checkMark.responds(to: #selector(updateView(_:))) {
let width = self.sizeObject.getValueBased(onSize: size)
self.checkboxWidth.constant = width
self.checkboxHeight.constant = width
self.checkMark.updateView(size)
}
})
}
func setCheckMarkLayer() {
checkedSquare.layer.cornerRadius = isRoundRectCheckMark ? 5.0 : 0
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Molecular // MARK: - Molecular
//-------------------------------------------------- //--------------------------------------------------

View File

@ -306,6 +306,8 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
self.checkedSquare.layer.cornerRadius = self.isRoundRectCheckMark ? 5.0f : 0; self.checkedSquare.layer.cornerRadius = self.isRoundRectCheckMark ? 5.0f : 0;
} }
// TODO:.....................................
#pragma mark - XIB Helpers #pragma mark - XIB Helpers
- (instancetype)awakeAfterUsingCoder:(NSCoder *)aDecoder { - (instancetype)awakeAfterUsingCoder:(NSCoder *)aDecoder {