Skip to content

Commit

Permalink
feat: support default value for ProcessIndicatorModel
Browse files Browse the repository at this point in the history
  • Loading branch information
guoyingtao committed Jun 21, 2023
1 parent 6894a63 commit a8e45e4
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 84 deletions.
6 changes: 3 additions & 3 deletions Example/InchwormExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ class ViewController: UIViewController {
}

func createSlider(with config: Config) -> UIView {
let model1 = ProcessIndicatorModel(sliderValueRangeType: .unilateral(limit: 30),
let model1 = ProcessIndicatorModel(sliderValueRangeType: .unilateral(limit: 30, defaultValue: 10),
normalIconImage: UIImage(named: "ic_flash_on")!.tinted(with: UIColor.white)!.cgImage!,
dimmedIconImage: UIImage(named: "ic_flash_on")!.tinted(with: UIColor.gray)!.cgImage!)

let model2 = ProcessIndicatorModel(sliderValueRangeType: .bilateral(limit: 40),
let model2 = ProcessIndicatorModel(sliderValueRangeType: .bilateral(limit: 40, defaultValue: 15),
normalIconImage: UIImage(named: "settings")!.tinted(with: UIColor.white)!.cgImage!,
dimmedIconImage: UIImage(named: "settings")!.tinted(with: UIColor.gray)!.cgImage!)

let model3 = ProcessIndicatorModel(sliderValueRangeType: .bilateral(limit: 50),
let model3 = ProcessIndicatorModel(sliderValueRangeType: .bilateral(limit: 50, defaultValue: -25),
normalIconImage: UIImage(named: "ic_camera_front")!.tinted(with: UIColor.white)!.cgImage!,
dimmedIconImage: UIImage(named: "ic_camera_front")!.tinted(with: UIColor.gray)!.cgImage!)

Expand Down
4 changes: 4 additions & 0 deletions Inchworm.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
5FE0BBA2235D4CDB007EFB8E /* Inchworm.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 5FE0BBA1235D4CDB007EFB8E /* Inchworm.podspec */; };
5FE0BBA5235DFB10007EFB8E /* Slider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FE0BBA3235DFB10007EFB8E /* Slider.swift */; };
5FE0BBA6235DFB10007EFB8E /* ProcessIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FE0BBA4235DFB10007EFB8E /* ProcessIndicatorView.swift */; };
F2058F2F2A42A383008DEBAA /* ProcessIndicatorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2058F2E2A42A383008DEBAA /* ProcessIndicatorViewModel.swift */; };
F2B4FDAA2A3CA65900667F22 /* SlideRulerPositionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2B4FDA92A3CA65900667F22 /* SlideRulerPositionHelper.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -44,6 +45,7 @@
5FE0BBA1235D4CDB007EFB8E /* Inchworm.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Inchworm.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
5FE0BBA3235DFB10007EFB8E /* Slider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Slider.swift; sourceTree = "<group>"; };
5FE0BBA4235DFB10007EFB8E /* ProcessIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessIndicatorView.swift; sourceTree = "<group>"; };
F2058F2E2A42A383008DEBAA /* ProcessIndicatorViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessIndicatorViewModel.swift; sourceTree = "<group>"; };
F2B4FDA92A3CA65900667F22 /* SlideRulerPositionHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideRulerPositionHelper.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -108,6 +110,7 @@
5FFD2417235E37FA00602F3A /* Source */ = {
isa = PBXGroup;
children = (
F2058F2E2A42A383008DEBAA /* ProcessIndicatorViewModel.swift */,
F2B4FDA92A3CA65900667F22 /* SlideRulerPositionHelper.swift */,
5F732BFD23578E57008B53DA /* Inchworm.swift */,
5FE0BBA3235DFB10007EFB8E /* Slider.swift */,
Expand Down Expand Up @@ -231,6 +234,7 @@
buildActionMask = 2147483647;
files = (
5FE0BBA6235DFB10007EFB8E /* ProcessIndicatorView.swift in Sources */,
F2058F2F2A42A383008DEBAA /* ProcessIndicatorViewModel.swift in Sources */,
F2B4FDAA2A3CA65900667F22 /* SlideRulerPositionHelper.swift in Sources */,
5FE0BBA5235DFB10007EFB8E /* Slider.swift in Sources */,
5F732BFE23578E57008B53DA /* Inchworm.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions Inchworm/Source/Inchworm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ public enum SliderOrientation {
}

public enum SliderValueRangeType {
case bilateral(limit: Int)
case unilateral(limit: Int)
case bilateral(limit: Int, defaultValue: Int = 0)
case unilateral(limit: Int, defaultValue: Int = 0)
}
38 changes: 26 additions & 12 deletions Inchworm/Source/ProcessIndicatorContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ProcessIndicatorContainer: UIView {
self?.setOrientations(for: $0)
}

rerangeIndicators()
reRangeIndicators()
setActiveIndicatorIndex(activeIndicatorIndex)
}

Expand All @@ -63,7 +63,7 @@ class ProcessIndicatorContainer: UIView {
backgroundSlideView.frame = bounds
}

func rerangeIndicators() {
func reRangeIndicators() {
let slideContentSize = getSlideContentSize()
backgroundSlideView.contentSize = CGSize(width: backgroundSlideView.frame.width + slideContentSize.width - iconLength, height: backgroundSlideView.frame.height)

Expand All @@ -78,8 +78,9 @@ class ProcessIndicatorContainer: UIView {
normalIconImage: CGImage?,
dimmedIconImage: CGImage?) {
let indicatorFrame = CGRect(x: 0, y: 0, width: iconLength, height: iconLength)
let viewModel = ProcessIndicatorViewModel(sliderValueRangeType: sliderValueRangeType)
let indicatorView = ProcessIndicatorView(frame: indicatorFrame,
sliderValueRangeType: sliderValueRangeType,
viewModel: viewModel,
normalIconImage: normalIconImage,
dimmedIconImage: dimmedIconImage)
indicatorView.delegate = self
Expand All @@ -89,7 +90,7 @@ class ProcessIndicatorContainer: UIView {
backgroundSlideView.addSubview(indicatorView)

setOrientations(for: indicatorView)
rerangeIndicators()
reRangeIndicators()
}

func setOrientations(for indicatorView: ProcessIndicatorView) {
Expand All @@ -111,15 +112,17 @@ class ProcessIndicatorContainer: UIView {
return CGSize(width: width, height: height)
}

func initialIndicatorActive() {
getActiveIndicator()?.initialActiveStatus()
}

func setActiveIndicatorIndex(_ index: Int = 0, animated: Bool = false) {
if index < 0 {
activeIndicatorIndex = 0
} else if index > progressIndicatorViewList.count - 1 {
activeIndicatorIndex = progressIndicatorViewList.count - 1
} else {
activeIndicatorIndex = index
guard index < progressIndicatorViewList.count else {
fatalError("Invalid index found")
}

activeIndicatorIndex = index

guard let indicator = getActiveIndicator() else {
return
}
Expand All @@ -134,13 +137,17 @@ class ProcessIndicatorContainer: UIView {
backgroundSlideView.setContentOffset(offset, animated: animated)
}

func getActiveIndicator() -> ProcessIndicatorView? {
private func getActiveIndicator() -> ProcessIndicatorView? {
guard 0..<progressIndicatorViewList.count ~= activeIndicatorIndex else {
return nil
}

return progressIndicatorViewList[activeIndicatorIndex]
}

func setProgress(_ progress: Float) {
getActiveIndicator()?.progress = progress
}
}

extension ProcessIndicatorContainer: UIScrollViewDelegate {
Expand Down Expand Up @@ -179,7 +186,14 @@ extension ProcessIndicatorContainer: UIScrollViewDelegate {

extension ProcessIndicatorContainer: ProcessIndicatorViewDelegate {
func didActive(_ processIndicatorView: ProcessIndicatorView) {
setActiveIndicatorIndex(processIndicatorView.index, animated: true)
if activeIndicatorIndex != processIndicatorView.index {
setActiveIndicatorIndex(processIndicatorView.index, animated: true)
}

progressIndicatorViewList
.filter { $0.index != activeIndicatorIndex }
.forEach { $0.deactive() }

didActive(processIndicatorView.progress)
}

Expand Down
103 changes: 52 additions & 51 deletions Inchworm/Source/ProcessIndicatorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@

import UIKit

protocol ProcessIndicatorViewDelegate {
protocol ProcessIndicatorViewDelegate: AnyObject {
func didActive(_ processIndicatorView: ProcessIndicatorView)
func didTempReset(_ processIndicatorView: ProcessIndicatorView)
func didRemoveTempReset(_ processIndicatorView: ProcessIndicatorView)
}

class ProcessIndicatorView: UIView {
weak var delegate: ProcessIndicatorViewDelegate?
var viewModel: ProcessIndicatorViewModel!

private var progressLayer = CAShapeLayer()
private var minusProgressLayer = CAShapeLayer()
private var trackLayer = CAShapeLayer()
Expand All @@ -31,16 +34,22 @@ class ProcessIndicatorView: UIView {
blue: 84.0 / 255.0,
alpha: 1)

var sliderValueRangeType: SliderValueRangeType!
var sliderValueRangeType: SliderValueRangeType {
viewModel.sliderValueRangeType
}

var normalIconImage: CGImage?
var dimmedIconImage: CGImage?
var index = 0

var active = false

var progress: Float = 0.0 {
didSet {
setProgress(progress)
var progress: Float {
get {
viewModel.progress
}

set {
viewModel.progress = newValue
}
}

Expand All @@ -50,8 +59,6 @@ class ProcessIndicatorView: UIView {
}
}

var delegate: ProcessIndicatorViewDelegate?

private var circlePath: UIBezierPath!

var progressColor = UIColor.white {
Expand Down Expand Up @@ -79,25 +86,35 @@ class ProcessIndicatorView: UIView {
}

init(frame: CGRect,
sliderValueRangeType: SliderValueRangeType,
viewModel: ProcessIndicatorViewModel,
normalIconImage: CGImage? = nil,
dimmedIconImage: CGImage? = nil) {
super.init(frame: frame)

self.sliderValueRangeType = sliderValueRangeType
self.viewModel = viewModel
self.normalIconImage = normalIconImage
self.dimmedIconImage = dimmedIconImage

createCircularPath()
createProgressNumber()
createIcon()
setupUIFrames()
change(to: .initial)

viewModel.didSetProgress = { [weak self] progressValue in
guard let self = self else { return }
self.setProgress(ratio: self.viewModel.progress, value: progressValue)
}

viewModel.setDefaultProgress()

if viewModel.progress == 0 {
change(to: .initial)
} else {
change(to: .editingOthers)
}

let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
addGestureRecognizer(tap)

NotificationCenter.default.addObserver(self, selector: #selector(handleActivited(notification:)), name: .ProgressIndicatorActivated, object: nil)
}

required init?(coder aDecoder: NSCoder) {
Expand All @@ -119,20 +136,23 @@ class ProcessIndicatorView: UIView {
minusProgressLayer.path = circlePath.reversing().cgPath
}

@objc func handleActivited(notification: Notification) {
guard let object = notification.object as? ProcessIndicatorView else {
return
func initialActiveStatus() {
active = true

if progress != 0 {
delegate?.didActive(self)
status = .editingSelf
}
}

if self !== object {
active = false

if status != .tempReset {
if getProgressValue() == 0 {
status = .initial
} else {
status = .editingOthers
}
func deactive() {
active = false

if status != .tempReset {
if viewModel.progress == 0 {
status = .initial
} else {
status = .editingOthers
}
}
}
Expand All @@ -156,8 +176,6 @@ class ProcessIndicatorView: UIView {

status = .editingSelf
}

NotificationCenter.default.post(name: .ProgressIndicatorActivated, object: self)
}

private func createIcon() {
Expand Down Expand Up @@ -197,24 +215,23 @@ class ProcessIndicatorView: UIView {
progressNumberLayer.contentsScale = UIScreen.main.scale
progressNumberLayer.string = "0"
progressNumberLayer.fontSize = 16

progressNumberLayer.alignmentMode = .center

layer.addSublayer(progressNumberLayer)
}

private func setProgress(_ progress: Float) {
private func setProgress(ratio progressRatio: Float, value progressValue: Int) {
status = .editingSelf

if progress > 0 {
if progressRatio > 0 {
progressLayer.isHidden = false
minusProgressLayer.isHidden = true

progressLayer.path = circlePath.cgPath
progressColor = UIColor(displayP3Red: 247.0 / 255.0, green: 198.0 / 255.0, blue: 0, alpha: 1)
trackColor = trackColorVlue
progressLayer.strokeColor = progressColor.cgColor
progressLayer.strokeEnd = abs(CGFloat(progress))
progressLayer.strokeEnd = abs(CGFloat(progressRatio))
progressNumberLayer.foregroundColor = progressColor.cgColor
} else {
progressLayer.isHidden = true
Expand All @@ -223,26 +240,15 @@ class ProcessIndicatorView: UIView {
minusProgressColor = .white
trackColor = minusTrackColorValue
minusProgressLayer.strokeColor = minusProgressColor.cgColor
minusProgressLayer.strokeEnd = abs(CGFloat(progress))
minusProgressLayer.strokeEnd = abs(CGFloat(progressRatio))
progressNumberLayer.foregroundColor = minusProgressColor.cgColor
}

trackLayer.strokeColor = trackColor.cgColor
progressNumberLayer.string = "\(getProgressValue())"
progressNumberLayer.string = "\(progressValue)"
}

func getProgressValue() -> Int {
switch sliderValueRangeType {
case .bilateral(let limit):
fallthrough
case .unilateral(let limit):
return Int(progress * Float(limit))
case .none:
return 0
}
}

func change(to status: IndicatorStatus) {

private func change(to status: IndicatorStatus) {
iconLayer.isHidden = false
progressNumberLayer.isHidden = true
trackLayer.strokeColor = trackColor.cgColor
Expand Down Expand Up @@ -274,11 +280,6 @@ class ProcessIndicatorView: UIView {
}
}

extension Notification.Name {
static let ProgressIndicatorActivated
= NSNotification.Name("ProgressIndicatorActivated")
}

enum IndicatorStatus {
case initial
case tempReset
Expand Down

0 comments on commit a8e45e4

Please sign in to comment.