Commit 9a2f1b36 by Orkhan Alikhanov

Refactored radiobutton/checkbutton stuff

parent b8b1b899
...@@ -43,11 +43,12 @@ open class BaseButtonGroup<T: Button>: View { ...@@ -43,11 +43,12 @@ open class BaseButtonGroup<T: Button>: View {
open override func sizeThatFits(_ size: CGSize) -> CGSize { open override func sizeThatFits(_ size: CGSize) -> CGSize {
let size = CGSize(width: size.width == 0 ? .greatestFiniteMagnitude : size.width, height: size.height == 0 ? .greatestFiniteMagnitude : size.height) let size = CGSize(width: size.width == 0 ? .greatestFiniteMagnitude : size.width, height: size.height == 0 ? .greatestFiniteMagnitude : size.height)
let availableW = size.width - grid.contentEdgeInsets.left - grid.contentEdgeInsets.right - grid.layoutEdgeInsets.left - grid.layoutEdgeInsets.right let availableW = size.width - grid.contentEdgeInsets.left - grid.contentEdgeInsets.right - grid.layoutEdgeInsets.left - grid.layoutEdgeInsets.right
var maxW: CGFloat = 0 let maxW = buttons.reduce(0) { max($0, $1.sizeThatFits(.init(width: availableW, height: .greatestFiniteMagnitude)).width) }
buttons.forEach { maxW = max(maxW, $0.sizeThatFits(.init(width: availableW, height: .greatestFiniteMagnitude)).width) }
var h = grid.contentEdgeInsets.top + grid.contentEdgeInsets.bottom + grid.layoutEdgeInsets.top + grid.layoutEdgeInsets.bottom + CGFloat(buttons.count - 1) * grid.interimSpace let h = buttons.reduce(0) { $0 + $1.sizeThatFits(.init(width: maxW, height: .greatestFiniteMagnitude)).height }
buttons.forEach { h += $0.sizeThatFits(.init(width: maxW, height: .greatestFiniteMagnitude)).height } + grid.contentEdgeInsets.top + grid.contentEdgeInsets.bottom
+ grid.layoutEdgeInsets.top + grid.layoutEdgeInsets.bottom
+ CGFloat(buttons.count - 1) * grid.interimSpace
return CGSize(width: maxW + grid.contentEdgeInsets.left + grid.contentEdgeInsets.right + grid.layoutEdgeInsets.left + grid.layoutEdgeInsets.right, height: min(h, size.height)) return CGSize(width: maxW + grid.contentEdgeInsets.left + grid.contentEdgeInsets.right + grid.layoutEdgeInsets.left + grid.layoutEdgeInsets.right, height: min(h, size.height))
} }
......
...@@ -12,7 +12,7 @@ import Motion ...@@ -12,7 +12,7 @@ import Motion
/// Implements common logic for CheckButton and RadioButton /// Implements common logic for CheckButton and RadioButton
open class BaseIconLayerButton: Button { open class BaseIconLayerButton: Button {
class var iconLayer: BaseIconLayer { fatalError("Has to be implemented by subclasses") } class var iconLayer: BaseIconLayer { fatalError("Has to be implemented by subclasses") }
lazy var iconLayer: BaseIconLayer = { return type(of: self).iconLayer }() lazy var iconLayer: BaseIconLayer = type(of: self).iconLayer
/// A Boolean value indicating whether the button is in the selected state /// A Boolean value indicating whether the button is in the selected state
/// ///
...@@ -185,15 +185,15 @@ internal class BaseIconLayer: CALayer { ...@@ -185,15 +185,15 @@ internal class BaseIconLayer: CALayer {
guard !isAnimating else { return } guard !isAnimating else { return }
prepareForFirstAnimation() prepareForFirstAnimation()
Motion.animate(duration: partialDuration, timingFunction: .easeInOut, animations: { Motion.animate(duration: Constants.partialDuration, timingFunction: .easeInOut, animations: {
self.isAnimating = true self.isAnimating = true
self.firstAnimation() self.firstAnimation()
}, completion: { }, completion: {
Motion.disable { Motion.disable {
self.prepareForSecondAnimation() self.prepareForSecondAnimation()
} }
Motion.delay(self.partialDuration * self.delayFactor) { Motion.delay(Constants.partialDuration * Constants.delayFactor) {
Motion.animate(duration: self.partialDuration, timingFunction: .easeInOut, animations: { Motion.animate(duration: Constants.partialDuration, timingFunction: .easeInOut, animations: {
self.secondAnimation() self.secondAnimation()
}, completion: { self.isAnimating = false }) }, completion: { self.isAnimating = false })
} }
...@@ -201,9 +201,12 @@ internal class BaseIconLayer: CALayer { ...@@ -201,9 +201,12 @@ internal class BaseIconLayer: CALayer {
} }
var sideLength: CGFloat { return frame.height } var sideLength: CGFloat { return frame.height }
let totalDuration = 0.5
private let delayFactor = 0.33 struct Constants {
private var partialDuration: TimeInterval { return totalDuration / (1.0 + delayFactor + 1.0) } static let totalDuration = 0.5
static let delayFactor = 0.33
static let partialDuration = totalDuration / (1.0 + delayFactor + 1.0)
}
} }
// MARK: - Helper extension // MARK: - Helper extension
......
...@@ -115,7 +115,7 @@ internal class CheckBoxLayer: BaseIconLayer { ...@@ -115,7 +115,7 @@ internal class CheckBoxLayer: BaseIconLayer {
checkMarkRightLayer.strokeEnd = 0.0001 checkMarkRightLayer.strokeEnd = 0.0001
checkMarkLayer.opacity = 0 checkMarkLayer.opacity = 0
checkMarkLayer.animate(#keyPath(CALayer.opacity), to: 1, dur: totalDuration * 0.1) checkMarkLayer.animate(#keyPath(CALayer.opacity), to: 1, dur: Constants.totalDuration * 0.1)
} else { } else {
borderLayer.borderWidth = borderLayerCenterDotBorderWidth borderLayer.borderWidth = borderLayerCenterDotBorderWidth
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
/// Unlike RadioButtonGroup, checking one check button that belongs to a check group *does not* unchecks any previously checked /// Unlike RadioButtonGroup, checking one check button that belongs to a check group *does not* unchecks any previously checked
/// check button within the same group. Intially, all of the check buttons are unchecked. /// check button within the same group. Intially, all of the check buttons are unchecked.
/// ///
/// The buttons are layout out by `Grid` system, so that changing properites of grid instance /// The buttons are laid out by `Grid` system, so that changing properites of grid instance
/// (e.g interimSpace) are reflected. /// (e.g interimSpace) are reflected.
open class CheckButtonGroup: BaseButtonGroup<CheckButton> { open class CheckButtonGroup: BaseButtonGroup<CheckButton> {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
/// Checking one radio button that belongs to a radio group unchecks any previously checked /// Checking one radio button that belongs to a radio group unchecks any previously checked
/// radio button within the same group. Intially, all of the radio buttons are unchecked. /// radio button within the same group. Intially, all of the radio buttons are unchecked.
/// ///
/// The buttons are layout out by `Grid` system, so that changing properites of grid instance /// The buttons are laid out by `Grid` system, so that changing properites of grid instance
/// (e.g interimSpace) are reflected. /// (e.g interimSpace) are reflected.
open class RadioButtonGroup: BaseButtonGroup<RadioButton> { open class RadioButtonGroup: BaseButtonGroup<RadioButton> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment