Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase customisation #50

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 114 additions & 81 deletions Sources/Slider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ open class Slider : UIControl {
addSubview(contentView)

contentView.addSubview(backgroundImageView)
contentView.addSubview(minimumImageView)
contentView.addSubview(maximumImageView)
contentView.addSubview(minimumImageView)
contentView.addSubview(maximumImageView)
contentView.addSubview(minimumLabel)
contentView.addSubview(maximumLabel)
contentView.addSubview(valueView)
Expand All @@ -81,15 +81,15 @@ open class Slider : UIControl {
open var fraction: CGFloat = 0 {
didSet {
updateValueViewText()
layoutValueView()
layoutValueView()
}
}

open var showFractionOnlyWhileTracking = false {
didSet {
updateValueViewText()
}
}
open var showFractionOnlyWhileTracking = false {
didSet {
updateValueViewText()
}
}

open var attributedTextForFraction: (CGFloat) -> (NSAttributedString) = { fraction in
let formatter = NumberFormatter()
Expand All @@ -99,78 +99,103 @@ open class Slider : UIControl {
return NSAttributedString(string: string)
}

open var valueViewMargin: CGFloat = ValueView.kLayoutMarginInset {
didSet {
if valueViewMargin < ValueView.kLayoutMarginInset {
valueViewMargin = ValueView.kLayoutMarginInset
}
layoutValueView()
}
}
open var valueViewMargin: CGFloat = ValueView.kLayoutMarginInset {
didSet {
if valueViewMargin < ValueView.kLayoutMarginInset {
valueViewMargin = ValueView.kLayoutMarginInset
}
layoutValueView()
}
}

private let valueView = ValueView()

open var valueViewTextColor: UIColor? {
didSet {
updateValueViewTextColor()
}
}

open var valueViewColor: UIColor? {
didSet {
updateValueViewColor()
}
}

private func updateValueViewColor() {
valueView.outerFillColor = contentViewColor
valueView.innerFillColor = valueViewColor
open var valueViewBorderColor: UIColor? {
didSet {
updateValueViewBorderColor()
}
}

open var valueViewSelectedTextColor: UIColor?

open var valueViewBorderSelectedColor: UIColor?

open var valueViewSelectedColor: UIColor?

private func updateValueViewColor(useSelectedColor: Bool = false) {
valueView.innerFillColor = useSelectedColor ? valueViewSelectedColor : valueViewColor
}

private func updateValueViewBorderColor(useSelectedColor: Bool = false) {
valueView.outerFillColor = useSelectedColor ? valueViewBorderSelectedColor : valueViewBorderColor
}

private func updateValueViewTextColor(useSelectedColor: Bool = false) {
valueView.textColor = useSelectedColor ? valueViewSelectedTextColor : valueViewTextColor
}

open var isAnimationEnabled = true
private(set) open var isSliderTracking = false
open var isAnimationEnabled = true
private(set) open var isSliderTracking = false

private func updateValueViewText() {
if !showFractionOnlyWhileTracking || isSliderTracking {
let text = attributedTextForFraction(fraction)
valueView.attributedText = text
} else {
valueView.attributedText = nil
}
if !showFractionOnlyWhileTracking || isSliderTracking {
let text = attributedTextForFraction(fraction)
valueView.attributedText = text
} else {
valueView.attributedText = nil
}
}

// MARK: - Images
// MARK: - Images

private let minimumImageView = UIImageView()
private let maximumImageView = UIImageView()
private let minimumImageView = UIImageView()
private let maximumImageView = UIImageView()

open var imagesMargin: CGFloat = 10 {
didSet {
layoutImageViews()
}
}
open var imagesMargin: CGFloat = 10 {
didSet {
layoutImageViews()
}
}

open var imagesColor: UIColor? {
didSet {
minimumImageView.tintColor = imagesColor
maximumImageView.tintColor = imagesColor
}
}
open var imagesColor: UIColor? {
didSet {
minimumImageView.tintColor = imagesColor
maximumImageView.tintColor = imagesColor
}
}

open func setMinimumImage(_ image: UIImage?) {
minimumImageView.image = image?.withRenderingMode(.alwaysTemplate)
layoutImageViews()
}
open func setMinimumImage(_ image: UIImage?) {
minimumImageView.image = image?.withRenderingMode(.alwaysTemplate)
layoutImageViews()
}

open func setMaximumImage(_ image: UIImage?) {
maximumImageView.image = image?.withRenderingMode(.alwaysTemplate)
layoutImageViews()
}
open func setMaximumImage(_ image: UIImage?) {
maximumImageView.image = image?.withRenderingMode(.alwaysTemplate)
layoutImageViews()
}

// MARK: - Labels

private let minimumLabel = UILabel()
private let maximumLabel = UILabel()

open var labelsMargin: CGFloat = 10 {
didSet {
layoutLabelsText()
}
}
open var labelsMargin: CGFloat = 10 {
didSet {
layoutLabelsText()
}
}

open func setMinimumLabelAttributedText(_ attributedText: NSAttributedString?) {
minimumLabel.attributedText = attributedText
Expand All @@ -186,11 +211,11 @@ open class Slider : UIControl {

private let backgroundImageView = UIImageView()

open var contentViewCornerRadius: CGFloat = 8 {
didSet {
layoutBackgroundImage()
}
}
open var contentViewCornerRadius: CGFloat = 8 {
didSet {
layoutBackgroundImage()
}
}

open var contentViewColor: UIColor? {
didSet {
Expand Down Expand Up @@ -226,7 +251,7 @@ open class Slider : UIControl {
filterView.mask?.frame = filterView.bounds

layoutBackgroundImage()
layoutImageViews()
layoutImageViews()
layoutLabelsText()
layoutValueView()
}
Expand All @@ -239,22 +264,22 @@ open class Slider : UIControl {
maximumLabel.frame = CGRect(x: bounds.maxX - labelsMargin - maximumLabel.bounds.width, y: bounds.midY - maximumLabel.bounds.midY, width: maximumLabel.bounds.width, height: maximumLabel.bounds.height).integral
}

private func layoutImageViews() {
let imageInset = ValueView.kLayoutMarginInset * 2
let imageSize = CGSize(width: bounds.height - imageInset * 2, height: bounds.height - imageInset * 2)
private func layoutImageViews() {
let imageInset = ValueView.kLayoutMarginInset * 2
let imageSize = CGSize(width: bounds.height - imageInset * 2, height: bounds.height - imageInset * 2)

minimumImageView.frame = CGRect(x: imagesMargin, y: imageInset, width: imageSize.width, height: imageSize.height).integral
minimumImageView.contentMode = .left
if let image = minimumImageView.image, image.size.width > minimumImageView.bounds.width || image.size.height > minimumImageView.bounds.height {
minimumImageView.contentMode = .scaleAspectFit
}
minimumImageView.frame = CGRect(x: imagesMargin, y: imageInset, width: imageSize.width, height: imageSize.height).integral
minimumImageView.contentMode = .left
if let image = minimumImageView.image, image.size.width > minimumImageView.bounds.width || image.size.height > minimumImageView.bounds.height {
minimumImageView.contentMode = .scaleAspectFit
}

maximumImageView.frame = CGRect(x: bounds.maxX - imagesMargin - imageSize.width, y: imageInset, width: imageSize.width, height: imageSize.height).integral
maximumImageView.contentMode = .right
if let image = maximumImageView.image, image.size.width > maximumImageView.bounds.width || image.size.height > maximumImageView.bounds.height {
maximumImageView.contentMode = .scaleAspectFit
}
}
maximumImageView.frame = CGRect(x: bounds.maxX - imagesMargin - imageSize.width, y: imageInset, width: imageSize.width, height: imageSize.height).integral
maximumImageView.contentMode = .right
if let image = maximumImageView.image, image.size.width > maximumImageView.bounds.width || image.size.height > maximumImageView.bounds.height {
maximumImageView.contentMode = .scaleAspectFit
}
}

private func layoutBackgroundImage() {
let inset = UIEdgeInsets(top: min(0, shadowOffset.height - shadowBlur), left: min(0, shadowOffset.width - shadowBlur), bottom: max(0, shadowOffset.height + shadowBlur) * -1, right: max(0, shadowOffset.width + shadowBlur) * -1)
Expand Down Expand Up @@ -284,18 +309,21 @@ open class Slider : UIControl {
override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let result = super.beginTracking(touch, with: event)
let x = touch.location(in: self).x
isSliderTracking = true
isSliderTracking = true
fraction = fractionForPositionX(x)
valueView.animateTrackingBegin()
sendActions(for: .valueChanged)
didBeginTracking?(self)
updateValueViewColor(useSelectedColor: true)
updateValueViewBorderColor(useSelectedColor: true)
updateValueViewTextColor(useSelectedColor: true)
return result
}

override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let result = super.continueTracking(touch, with: event)
let x = touch.location(in: self).x
isSliderTracking = true
isSliderTracking = true
fraction = fractionForPositionX(x)
filterView.center.x = valueView.center.x
sendActions(for: .valueChanged)
Expand All @@ -304,18 +332,24 @@ open class Slider : UIControl {

override open func endTracking(_ touch: UITouch?, with event: UIEvent?) {
super.endTracking(touch, with: event)
isSliderTracking = false
isSliderTracking = false
valueView.animateTrackingEnd()
updateValueViewText()
updateValueViewText()
didEndTracking?(self)
updateValueViewColor()
updateValueViewBorderColor()
updateValueViewTextColor()
}

override open func cancelTracking(with event: UIEvent?) {
super.cancelTracking(with: event)
isSliderTracking = false
isSliderTracking = false
valueView.animateTrackingEnd()
updateValueViewText()
updateValueViewText()
didEndTracking?(self)
updateValueViewColor()
updateValueViewBorderColor()
updateValueViewTextColor()
}

private func boundsForValueViewCenter() -> CGRect {
Expand Down Expand Up @@ -381,5 +415,4 @@ open class Slider : UIControl {
(filterView.mask as? UIImageView)?.image = filterViewMask
}
}

}
34 changes: 21 additions & 13 deletions Sources/ValueView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import pop

class ValueView : UIView {

static let kLayoutMarginInset: CGFloat = 4
static let kLayoutMarginInset: CGFloat = 1

// MARK: - Initialization

Expand Down Expand Up @@ -54,6 +54,12 @@ class ValueView : UIView {
}
}

var textColor: UIColor? {
didSet {
textLabel.textColor = textColor
}
}

// MARK: - Text Label

private let textLabel = UILabel()
Expand All @@ -63,17 +69,20 @@ class ValueView : UIView {
return textLabel.attributedText
}
set {
if let newValue = newValue {
// apply centered horizontal alignment
let string = newValue.mutableCopy() as! NSMutableAttributedString
let paragraph = (string.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle ?? NSParagraphStyle()).mutableCopy() as! NSMutableParagraphStyle
paragraph.alignment = .center
string.addAttribute(.paragraphStyle, value: paragraph, range: NSMakeRange(0, string.length))
textLabel.attributedText = string
} else {
textLabel.attributedText = nil
}
}
if let newValue = newValue {
// apply centered horizontal alignment
let string = newValue.mutableCopy() as! NSMutableAttributedString
let paragraph = (string.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle ?? NSParagraphStyle()).mutableCopy() as! NSMutableParagraphStyle
paragraph.alignment = .center
string.addAttribute(.paragraphStyle, value: paragraph, range: NSMakeRange(0, string.length))
if let textColor = textColor {
string.addAttribute(.foregroundColor, value: textColor, range: NSMakeRange(0, string.length))
}
textLabel.attributedText = string
} else {
textLabel.attributedText = nil
}
}
}

// MARK: - Laying out Subviews
Expand Down Expand Up @@ -119,5 +128,4 @@ class ValueView : UIView {
shapeView.layer.pop_add(animation, forKey: "bounce")
}
}

}