Stars: Change UIProgressView to draw due to apple defect
Remove unneeded constant Re-prioritized Create and update stars functions
This commit is contained in:
parent
4c15bef289
commit
ad7e88082c
@ -18,15 +18,28 @@ import Foundation
|
|||||||
public var starModel: StarModel? {
|
public var starModel: StarModel? {
|
||||||
return model as? StarModel
|
return model as? StarModel
|
||||||
}
|
}
|
||||||
public var progressBar = UIProgressView(progressViewStyle: .bar)
|
@Percent public var percent = 0 {
|
||||||
public var percent: Int = 0
|
didSet {
|
||||||
|
updateAccessibilityLabel()
|
||||||
|
setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
public var size: CGFloat = 30 {
|
public var size: CGFloat = 30 {
|
||||||
didSet {
|
didSet {
|
||||||
widthConstraint?.constant = size
|
widthConstraint?.constant = size
|
||||||
setNeedsDisplay()
|
setNeedsDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public var borderColor: Color = Color(uiColor: .mvmBlack)
|
public var fillColor = UIColor.mvmBlack {
|
||||||
|
didSet {
|
||||||
|
setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var borderColor: CGColor = UIColor.mvmBlack.cgColor {
|
||||||
|
didSet {
|
||||||
|
setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Constraints
|
// MARK: - Constraints
|
||||||
@ -38,7 +51,14 @@ import Foundation
|
|||||||
// MARK: - State Handling
|
// MARK: - State Handling
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
open override func draw(_ rect: CGRect) {
|
open override func draw(_ rect: CGRect) {
|
||||||
//Draw the heart
|
//Draw progress
|
||||||
|
let width = bounds.size.width * percent / 100.0
|
||||||
|
let progressRect = CGRect(x: 0, y: 0, width: width, height: bounds.height)
|
||||||
|
fillColor.set()
|
||||||
|
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||||
|
context.fill(progressRect)
|
||||||
|
|
||||||
|
//Draw the star
|
||||||
starLayer?.removeFromSuperlayer()
|
starLayer?.removeFromSuperlayer()
|
||||||
let star = drawStar()
|
let star = drawStar()
|
||||||
layer.addSublayer(star)
|
layer.addSublayer(star)
|
||||||
@ -84,18 +104,40 @@ import Foundation
|
|||||||
shapeLayer.fillColor = UIColor.clear.cgColor
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
||||||
shapeLayer.opacity = 1.0
|
shapeLayer.opacity = 1.0
|
||||||
shapeLayer.lineWidth = 1
|
shapeLayer.lineWidth = 1
|
||||||
shapeLayer.strokeColor = borderColor.cgColor
|
shapeLayer.strokeColor = borderColor
|
||||||
return shapeLayer
|
return shapeLayer
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - MoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
borderColor = UIColor.mvmBlack.cgColor
|
||||||
|
fillColor = .mvmBlack
|
||||||
|
percent = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
guard let model = model as? StarModel else { return }
|
||||||
|
percent = model.percent
|
||||||
|
if let fillColor = model.fillColor?.uiColor {
|
||||||
|
self.fillColor = fillColor
|
||||||
|
}
|
||||||
|
if let borderColor = model.borderColor?.cgColor {
|
||||||
|
self.borderColor = borderColor
|
||||||
|
}
|
||||||
|
size = model.size
|
||||||
|
updateAccessibilityLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - MVMCoreViewProtocol
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
progressBar.translatesAutoresizingMaskIntoConstraints = false
|
backgroundColor = .clear
|
||||||
addSubview(progressBar)
|
|
||||||
NSLayoutConstraint.constraintPinSubview(toSuperview: progressBar)
|
|
||||||
widthConstraint = widthAnchor.constraint(equalToConstant: 30)
|
widthConstraint = widthAnchor.constraint(equalToConstant: 30)
|
||||||
widthConstraint?.isActive = true
|
widthConstraint?.isActive = true
|
||||||
heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
|
heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
|
||||||
@ -104,23 +146,9 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
|
||||||
super.set(with: model, delegateObject, additionalData)
|
|
||||||
guard let model = model as? StarModel else { return }
|
|
||||||
progressBar.progress = Float((model.percent) / 100.0)
|
|
||||||
percent = Int(model.percent)
|
|
||||||
progressBar.progressTintColor = (model.fillColor != nil) ? model.fillColor?.uiColor : .mvmBlack
|
|
||||||
progressBar.trackTintColor = .mvmWhite
|
|
||||||
if let border = model.borderColor {
|
|
||||||
borderColor = border
|
|
||||||
}
|
|
||||||
size = model.size
|
|
||||||
updateAccessibilityLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Accessibility
|
// MARK: - Accessibility
|
||||||
func updateAccessibilityLabel() {
|
func updateAccessibilityLabel() {
|
||||||
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "star")
|
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "star")
|
||||||
accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "star_percent") ?? "", percent)
|
accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "star_percent") ?? "", Int(percent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@ open class Stars: View {
|
|||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var stack = UIStackView()
|
private var stack = UIStackView()
|
||||||
public var starElements = [Star]()
|
|
||||||
public var starsModel: StarsModel? {
|
public var starsModel: StarsModel? {
|
||||||
return model as? StarsModel
|
return model as? StarsModel
|
||||||
}
|
}
|
||||||
@ -23,20 +22,17 @@ open class Stars: View {
|
|||||||
private var starsFilledValue: Float = 0
|
private var starsFilledValue: Float = 0
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - MVMCoreViewProtocol
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
stack.translatesAutoresizingMaskIntoConstraints = false
|
stack.translatesAutoresizingMaskIntoConstraints = false
|
||||||
addSubview(stack)
|
|
||||||
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
|
||||||
let leading = stack.leadingAnchor.constraint(equalTo: self.leadingAnchor)
|
|
||||||
leading.priority = UILayoutPriority(rawValue: 1000)
|
|
||||||
leading.isActive = true
|
|
||||||
heightConstraint = heightAnchor.constraint(equalToConstant: 30)
|
|
||||||
heightConstraint?.isActive = true
|
|
||||||
stack.axis = .horizontal
|
stack.axis = .horizontal
|
||||||
stack.spacing = itemSpacing
|
stack.spacing = itemSpacing
|
||||||
|
addSubview(stack)
|
||||||
|
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
||||||
|
heightConstraint = heightAnchor.constraint(equalToConstant: 30)
|
||||||
|
heightConstraint?.isActive = true
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
@ -46,70 +42,69 @@ open class Stars: View {
|
|||||||
stack.updateView(size)
|
stack.updateView(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - MoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
super.set(with: model, delegateObject, additionalData)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
self.delegateObject = delegateObject
|
self.delegateObject = delegateObject
|
||||||
createStar()
|
createStars()
|
||||||
updateStar()
|
updateStars()
|
||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func reset() {
|
||||||
|
stack.subviews.forEach({$0.removeFromSuperview()})
|
||||||
|
super.reset()
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// MARK: - Methods
|
// MARK: - Methods
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
func createStar() {
|
func createStars() {
|
||||||
if let starsModel = starsModel {
|
guard let starsModel = starsModel else { return }
|
||||||
for starModel in starsModel.stars {
|
for starModel in starsModel.stars {
|
||||||
let star = Star()
|
let star = Star(model: starModel, delegateObject, nil)
|
||||||
star.set(with: starModel, delegateObject, nil)
|
star.isAccessibilityElement = false
|
||||||
stack.addArrangedSubview(star)
|
stack.addArrangedSubview(star)
|
||||||
starElements.append(star)
|
|
||||||
star.isAccessibilityElement = false
|
|
||||||
//Star model colors should take priority over stars.
|
|
||||||
if let borderColor = starsModel.borderColor, starModel.borderColor == nil {
|
|
||||||
star.borderColor = borderColor
|
|
||||||
}
|
|
||||||
if let fillColor = starsModel.fillColor, starModel.fillColor == nil {
|
|
||||||
star.progressBar.progressTintColor = fillColor.uiColor
|
|
||||||
}
|
|
||||||
if let backgroundColor = starsModel.starBackgroundColor, starModel.backgroundColor == nil {
|
|
||||||
star.backgroundColor = backgroundColor.uiColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
heightConstraint?.constant = starsModel.size
|
|
||||||
}
|
}
|
||||||
|
heightConstraint?.constant = starsModel.size
|
||||||
}
|
}
|
||||||
|
|
||||||
//Update star progress and size with starsModel values
|
func updateStars() {
|
||||||
func updateStar() {
|
guard let starsModel = starsModel else { return }
|
||||||
if let starsModel = starsModel {
|
let percentRequiredToFillStarFully = CGFloat(100/(stack.arrangedSubviews.count))
|
||||||
let percentRequiredToFillStarFully = CGFloat(100/(starElements.count))
|
let numberOfFilledStars = Int(starsModel.percent/percentRequiredToFillStarFully)
|
||||||
let numberOfFilledStars = Int(starsModel.percent/percentRequiredToFillStarFully)
|
starsFilledValue = Float(numberOfFilledStars)
|
||||||
starsFilledValue = Float(numberOfFilledStars)
|
for case let (index, star as Star) in stack.arrangedSubviews.enumerated() {
|
||||||
for (index, star) in starElements.enumerated() {
|
//Star model colors should take priority over stars.
|
||||||
//Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars
|
if let borderColor = starsModel.borderColor?.cgColor, star.starModel?.borderColor == nil {
|
||||||
if index < numberOfFilledStars {
|
star.borderColor = borderColor
|
||||||
star.progressBar.progress = 1
|
|
||||||
} else if index == numberOfFilledStars {
|
|
||||||
let remainingProgress = (starsModel.percent).truncatingRemainder(dividingBy: percentRequiredToFillStarFully)
|
|
||||||
let fillPercent = remainingProgress/percentRequiredToFillStarFully
|
|
||||||
starsFilledValue += Float(fillPercent)
|
|
||||||
star.progressBar.progress = Float(fillPercent)
|
|
||||||
} else {
|
|
||||||
star.progressBar.progress = 0
|
|
||||||
}
|
|
||||||
star.size = starsModel.size
|
|
||||||
}
|
}
|
||||||
|
if let fillColor = starsModel.fillColor?.uiColor, star.starModel?.fillColor == nil {
|
||||||
|
star.fillColor = fillColor
|
||||||
|
}
|
||||||
|
if let backgroundColor = starsModel.starBackgroundColor?.uiColor, star.starModel?.backgroundColor == nil {
|
||||||
|
star.backgroundColor = backgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars
|
||||||
|
if index < numberOfFilledStars {
|
||||||
|
star.percent = 100
|
||||||
|
} else if index == numberOfFilledStars {
|
||||||
|
let remainingProgress = (starsModel.percent).truncatingRemainder(dividingBy: percentRequiredToFillStarFully)
|
||||||
|
let fillPercent = remainingProgress/percentRequiredToFillStarFully
|
||||||
|
starsFilledValue += Float(fillPercent)
|
||||||
|
star.percent = fillPercent * 100
|
||||||
|
} else {
|
||||||
|
star.percent = 0
|
||||||
|
}
|
||||||
|
star.size = starsModel.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func reset() {
|
|
||||||
super.reset()
|
|
||||||
stack.subviews.forEach({$0.removeFromSuperview()})
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Accessibility
|
// MARK: - Accessibility
|
||||||
func updateAccessibilityLabel() {
|
func updateAccessibilityLabel() {
|
||||||
accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "stars_filled") ?? "", starsFilledValue, starElements.count)
|
accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "stars_filled") ?? "", starsFilledValue, stack.arrangedSubviews.count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,12 +47,8 @@ import Foundation
|
|||||||
if let percent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .percent) {
|
if let percent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .percent) {
|
||||||
self.percent = percent
|
self.percent = percent
|
||||||
}
|
}
|
||||||
if let borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) {
|
borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor)
|
||||||
self.borderColor = borderColor
|
fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor)
|
||||||
}
|
|
||||||
if let fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) {
|
|
||||||
self.fillColor = fillColor
|
|
||||||
}
|
|
||||||
if let size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size) {
|
if let size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size) {
|
||||||
self.size = size
|
self.size = size
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user