DYScrollRulerView.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. //
  2. // DYScrollRulerView.swift
  3. // YKScrollRulerSwift
  4. //
  5. // Created by Daniel Yao on 16/11/22.
  6. // Copyright © 2016年 Daniel Yao. All rights reserved.
  7. //
  8. import UIKit
  9. fileprivate let TextRulerFont = UIFont.systemFont(ofSize: 11)
  10. fileprivate let RulerLineColor = UIColor.gray
  11. fileprivate let RulerGap = 4
  12. fileprivate let RulerLong = 9
  13. fileprivate let RulerShort = 4
  14. fileprivate let TriangleWidth = 16
  15. fileprivate let CollectionHeight = 30
  16. fileprivate let TextColorWhiteAlpha:CGFloat = 1.0
  17. fileprivate func alerts(vc:UIViewController,str:String){
  18. // let alert = UIAlertController.init(title: "提醒", message: str, preferredStyle: UIAlertController.Style.alert)
  19. // let action:UIAlertAction = UIAlertAction.init(title: "OK", style: UIAlertAction.Style.default, handler: { (action) in
  20. //
  21. // })
  22. // alert.addAction(action)
  23. // vc.present(alert, animated: true, completion: nil)
  24. }
  25. /***************DY************分************割************线***********/
  26. class DYTriangleView: UIView {
  27. var triangleColor:UIColor?
  28. override init(frame: CGRect) {
  29. super.init(frame: frame)
  30. }
  31. required init?(coder: NSCoder) {
  32. fatalError("init(coder:) has not been implemented")
  33. }
  34. override func draw(_ rect: CGRect) {
  35. let line1 = UIView()
  36. line1.backgroundColor = UIColor(hexString: "#573F95")
  37. addSubview(line1)
  38. line1.frame = CGRect(x: TriangleWidth / 2 - 2, y: 0, width: 4, height: 1)
  39. let line2 = UIView()
  40. line2.backgroundColor = UIColor(hexString: "#573F95")
  41. addSubview(line2)
  42. line2.frame = CGRect(x: Double(TriangleWidth / 2) - 0.5, y: 0, width: 1, height: 30)
  43. let line3 = UIView()
  44. line3.backgroundColor = UIColor(hexString: "#573F95")
  45. addSubview(line3)
  46. line3.frame = CGRect(x: TriangleWidth / 2 - 2, y: 30, width: 4, height: 1)
  47. let line4 = UIView()
  48. line4.backgroundColor = UIColor(hexString: "#573F95")
  49. addSubview(line4)
  50. line4.frame = CGRect(x: TriangleWidth / 2 - 2 , y: (30 - 13) / 2 , width: 4, height: 13)
  51. }
  52. }
  53. /***************DY************分************割************线***********/
  54. class DYRulerView: UIView {
  55. var minValue:Float = 0.0
  56. var maxValue:Float = 0.0
  57. var unit:String = ""
  58. var step:Float = 0.0
  59. var betweenNumber = 0
  60. override func draw(_ rect: CGRect) {
  61. let startX:CGFloat = 0
  62. let lineCenterX = CGFloat(RulerGap)
  63. let shorttopY:CGFloat = (rect.size.height - CGFloat(RulerShort)) / 2
  64. let longtopY:CGFloat = (rect.size.height - CGFloat(RulerLong)) / 2
  65. let shortLineY = (shorttopY + CGFloat(RulerShort))
  66. let longLineY = (longtopY + CGFloat(RulerLong))
  67. let context = UIGraphicsGetCurrentContext()
  68. context?.setLineWidth(1)
  69. context?.setLineCap(CGLineCap.butt)
  70. context?.setStrokeColor(red: 101/255, green: 112/255, blue: 133/255, alpha: 1.0)
  71. for i in 0...betweenNumber {
  72. print(i)
  73. if i%betweenNumber == 0 {
  74. context?.move(to: CGPoint.init(x: startX+lineCenterX*CGFloat(i), y: longtopY))
  75. let num = Float(i)*step+minValue
  76. print(unit)
  77. var numStr = String(format: "%.f%@", num,unit)
  78. if num > 1000000 {
  79. numStr = String(format: "%f万%@", num/10000,unit)
  80. }
  81. print(i,step,minValue)
  82. // let attribute:Dictionary = [NSAttributedStringKey.font:TextRulerFont,NSAttributedStringKey.foregroundColor:UIColor.init(white: TextColorWhiteAlpha, alpha: 1.0)]
  83. // let width = numStr.boundingRect(
  84. // with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
  85. // options: NSStringDrawingOptions.usesLineFragmentOrigin,
  86. // attributes: attribute,context: nil).size.width
  87. // numStr.draw(in: CGRect.init(x: startX+lineCenterX*CGFloat(i)-width/2, y: longLineY+10, width: width, height: 14), withAttributes: attribute)
  88. context!.addLine(to: CGPoint.init(x: startX+lineCenterX*CGFloat(i), y: longLineY))
  89. }else{
  90. context?.move(to: CGPoint.init(x: startX+lineCenterX*CGFloat(i), y: shorttopY))
  91. context!.addLine(to: CGPoint.init(x: startX+lineCenterX*CGFloat(i), y: shortLineY))
  92. }
  93. context!.strokePath()
  94. }
  95. }
  96. }
  97. /***************DY************分************割************线***********/
  98. class DYHeaderRulerView: UIView {
  99. var headerMinValue = 0
  100. var headerUnit = ""
  101. override func draw(_ rect: CGRect) {
  102. let longLineY = rect.size.height - CGFloat(RulerShort)
  103. let context = UIGraphicsGetCurrentContext()
  104. context?.setStrokeColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
  105. context?.setLineWidth(1.0)
  106. context?.setLineCap(CGLineCap.butt)
  107. context?.move(to: CGPoint.init(x: rect.size.width, y: 0))
  108. var numStr:NSString = NSString(format: "%d%@", headerMinValue,headerUnit)
  109. if headerMinValue > 1000000 {
  110. numStr = NSString(format: "%f万%@", headerMinValue/10000,headerUnit)
  111. }
  112. let attribute:Dictionary = [NSAttributedString.Key.font:TextRulerFont,NSAttributedString.Key.foregroundColor:UIColor.init(white: TextColorWhiteAlpha, alpha: 1.0)]
  113. let width = numStr.boundingRect(with: CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions(rawValue: 0), attributes: attribute, context: nil).size.width
  114. numStr.draw(in: CGRect.init(x: rect.size.width-width/2, y: longLineY+10, width: width, height: 14), withAttributes: attribute)
  115. context?.addLine(to: CGPoint.init(x: rect.size.width, y: longLineY))
  116. context?.strokePath()
  117. }
  118. }
  119. /***************DY************分************割************线***********/
  120. class DYFooterRulerView: UIView {
  121. var footerMaxValue = 0
  122. var footerUnit = ""
  123. override func draw(_ rect: CGRect) {
  124. let longLineY = Int(rect.size.height) - RulerShort
  125. let context = UIGraphicsGetCurrentContext()
  126. context?.setStrokeColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
  127. context?.setLineWidth(1.0)
  128. context?.setLineCap(CGLineCap.butt)
  129. context?.move(to: CGPoint.init(x: 0, y: 0))
  130. var numStr:NSString = NSString(format: "%d%@", footerMaxValue,footerUnit)
  131. if footerMaxValue > 1000000 {
  132. numStr = NSString(format: "%f万%@", footerMaxValue/10000,footerUnit)
  133. }
  134. let attribute:Dictionary = [NSAttributedString.Key.font:TextRulerFont,NSAttributedString.Key.foregroundColor:UIColor.init(white: TextColorWhiteAlpha, alpha: 1.0)]
  135. let width = numStr.boundingRect(with: CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions(rawValue: 0), attributes: attribute, context: nil).size.width
  136. numStr.draw(in: CGRect.init(x: 0-width/2, y: CGFloat(longLineY+10), width: width, height:CGFloat(14)), withAttributes: attribute)
  137. context?.addLine(to: CGPoint.init(x: 0, y: longLineY))
  138. context?.strokePath()
  139. }
  140. }
  141. /***************DY************分************割************线***********/
  142. protocol DYScrollRulerDelegate:NSObjectProtocol {
  143. func dyScrollRulerViewValueChange(rulerView:DYScrollRulerView,value:Float)
  144. }
  145. class DYScrollRulerView: UIView {
  146. /*
  147. // Only override draw() if you perform custom drawing.
  148. // An empty implementation adversely affects performance during animation.
  149. override func draw(_ rect: CGRect) {
  150. // Drawing code
  151. }
  152. */
  153. weak var delegate:DYScrollRulerDelegate?
  154. var scrollByHand = true
  155. var triangleColor:UIColor? = nil
  156. var bgColor:UIColor? = nil
  157. var stepNum = 0//分多少个大区
  158. private var redLine:UIImageView?
  159. private var fileRealValue:Float = 0.0
  160. var rulerUnit:String = ""
  161. var minValue:Float = 0.0
  162. var maxValue:Float = 0.0
  163. var step:Float = 0.0 //间隔值,每两条相隔多少值
  164. var betweenNum:Int = 0
  165. var currentVC:UIViewController?
  166. class func rulerViewHeight() -> Int {
  167. return 40+20+CollectionHeight
  168. }
  169. init(frame: CGRect,tminValue:Float,tmaxValue:Float,tstep:Float,tunit:String,tNum:Int,viewcontroller:UIViewController?) {
  170. super.init(frame: frame)
  171. minValue = tminValue
  172. maxValue = tmaxValue
  173. betweenNum = tNum
  174. step = tstep
  175. stepNum = Int((tmaxValue - tminValue)/step)/betweenNum
  176. rulerUnit = tunit
  177. bgColor = UIColor.white
  178. currentVC = viewcontroller
  179. triangleColor = UIColor.orange
  180. self.backgroundColor = UIColor.white
  181. lazyValueTF.frame = CGRect.init(x: self.bounds.size.width/2-60, y: 10, width: 80, height: 20)
  182. self.addSubview(self.lazyValueTF)
  183. lazyTriangle.frame = CGRect.init(x: self.bounds.size.width/2-0.5 - CGFloat(TriangleWidth)/2, y: lazyValueTF.frame.maxY, width: CGFloat(TriangleWidth), height: CGFloat(30))
  184. lazyUnitLab.frame = CGRect.init(x: lazyValueTF.frame.maxX+10, y: lazyValueTF.frame.minY, width: 40, height: 40)
  185. lazyOKBtn.frame = CGRect.init(x: lazyUnitLab.frame.maxX+10, y: lazyValueTF.frame.minY+5, width: 40, height: 30)
  186. let circle = UIView(frame: CGRect(x: self.bounds.size.width/2-0.5 - CGFloat(30)/2, y: lazyValueTF.frame.maxY, width: 30, height: 30))
  187. circle.backgroundColor = UIColor(white: 1, alpha: 0.6)
  188. circle.layer.masksToBounds = true
  189. circle.layer.cornerRadius = 15
  190. self.addSubview(self.lazyUnitLab)
  191. // self.addSubview(self.lazyOKBtn)
  192. self.addSubview(self.lazyCollectionView)
  193. addSubview(circle)
  194. self.addSubview(self.lazyTriangle)
  195. self.lazyCollectionView.frame = CGRect.init(x: 0, y:self.lazyValueTF.frame.maxY, width: self.bounds.size.width, height: CGFloat(CollectionHeight))
  196. self.lazyUnitLab.text = tunit
  197. }
  198. required init?(coder aDecoder: NSCoder) {
  199. fatalError("init(coder:) has not been implemented")
  200. }
  201. lazy var lazyValueTF: UITextField = {[unowned self] in
  202. let zyValueTF = UITextField()
  203. zyValueTF.isUserInteractionEnabled = true
  204. // #05CFAB
  205. zyValueTF.textColor = UIColor(hexString: "#573F95")
  206. zyValueTF.defaultTextAttributes = [NSAttributedString.Key.font:UIFont(name: Alibaba_PuHuiTi_Medium, size: 11),NSAttributedString.Key.foregroundColor : UIColor(hexString: "#573F95")]
  207. zyValueTF.isEnabled = false
  208. zyValueTF.textAlignment = NSTextAlignment.right
  209. zyValueTF.delegate = self
  210. zyValueTF.keyboardType = UIKeyboardType.numbersAndPunctuation
  211. zyValueTF.returnKeyType = UIReturnKeyType.done
  212. return zyValueTF
  213. }()
  214. lazy var lazyOKBtn:UIButton = {
  215. let okBtn = UIButton.init(type: UIButton.ButtonType.custom)
  216. okBtn.setTitle("OK", for: UIControl.State.normal)
  217. okBtn.setTitleColor(UIColor.init(white: 0.7, alpha: 1.0), for: UIControl.State.highlighted)
  218. okBtn.setTitleColor(UIColor.white, for: UIControl.State.normal)
  219. okBtn.addTarget(self, action: #selector(DYScrollRulerView.editDone), for: UIControl.Event.touchUpInside)
  220. okBtn.backgroundColor = UIColor.gray
  221. okBtn.layer.cornerRadius = 5.0
  222. return okBtn
  223. }()
  224. lazy var lazyUnitLab: UILabel = {
  225. let zyUnitLab = UILabel()
  226. zyUnitLab.textColor = UIColor.red
  227. return zyUnitLab
  228. }()
  229. lazy var lazyCollectionView: UICollectionView = {[unowned self]in
  230. let flowLayout = UICollectionViewFlowLayout()
  231. flowLayout.scrollDirection = UICollectionView.ScrollDirection.horizontal
  232. flowLayout.sectionInset = UIEdgeInsets.init(top: 0, left: 0, bottom: 0, right: 0)
  233. let zyCollectionView:UICollectionView = UICollectionView.init(frame: CGRect.init(x: 0, y: 0, width: self.bounds.size.width, height: CGFloat(CollectionHeight)), collectionViewLayout: flowLayout)
  234. zyCollectionView.backgroundColor = UIColor(hexString: "#E9EFEC")
  235. zyCollectionView.bounces = true
  236. zyCollectionView.showsHorizontalScrollIndicator = false
  237. zyCollectionView.showsVerticalScrollIndicator = false
  238. zyCollectionView.delegate = self
  239. zyCollectionView.dataSource = self
  240. zyCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "headCell")
  241. zyCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "footerCell")
  242. zyCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "customeCell")
  243. return zyCollectionView
  244. }()
  245. lazy var lazyTriangle: DYTriangleView = {
  246. let triangleView = DYTriangleView()
  247. triangleView.backgroundColor = UIColor.clear
  248. triangleView.triangleColor = UIColor.blue
  249. return triangleView
  250. }()
  251. @objc fileprivate func didChangeCollectionValue() {
  252. let textFieldValue = Float(lazyValueTF.text!)
  253. if (textFieldValue!-minValue)>=0 {
  254. self.setRealValueAndAnimated(realValue: (textFieldValue!-minValue)/step, animated: true)
  255. }
  256. }
  257. @objc fileprivate func setRealValueAndAnimated(realValue:Float,animated:Bool){
  258. fileRealValue = realValue
  259. lazyValueTF.text = String.init(format: "%.1f", fileRealValue*step+minValue)
  260. lazyCollectionView.setContentOffset(CGPoint.init(x: Int(realValue)*RulerGap, y: 0), animated: animated)
  261. }
  262. func setDefaultValueAndAnimated(defaultValue:Float,animated:Bool){
  263. fileRealValue = defaultValue
  264. lazyValueTF.text = String.init(format: "%.1f", defaultValue)
  265. lazyCollectionView.setContentOffset(CGPoint.init(x: Int((defaultValue-minValue)/step) * RulerGap, y: 0), animated: animated)
  266. }
  267. @objc func editDone(){
  268. let currentText:NSString = lazyValueTF.text! as NSString
  269. if !self.judgeTextsHasWord(texts: currentText as String){
  270. alerts(vc: currentVC!, str: "请输入数字")
  271. return
  272. }
  273. lazyValueTF.resignFirstResponder()
  274. if currentText.floatValue > maxValue{
  275. lazyValueTF.text = String.init(format: "%.1f", maxValue)
  276. self.perform(#selector(self.didChangeCollectionValue), with: nil, afterDelay: 0)
  277. }else if currentText.floatValue <= minValue || currentText.length == 0{
  278. lazyValueTF.text = String.init(format: "%.1f", minValue)
  279. self.perform(#selector(self.didChangeCollectionValue), with: nil, afterDelay: 1)
  280. }else{
  281. NSObject.cancelPreviousPerformRequests(withTarget: self)
  282. self.perform(#selector(self.didChangeCollectionValue), with: nil, afterDelay: 1)
  283. }
  284. }
  285. func judgeTextsHasWord(texts:String) -> Bool{
  286. let scan:Scanner = Scanner.init(string: texts)
  287. var value:Float = 0.0
  288. return scan.scanFloat(&value) && scan.isAtEnd
  289. }
  290. }
  291. extension DYScrollRulerView:UICollectionViewDataSource{
  292. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  293. return 2+stepNum
  294. }
  295. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  296. if indexPath.item == 0 {
  297. let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "headCell", for: indexPath)
  298. var headerView:DYHeaderRulerView? = cell.contentView.viewWithTag(1000) as?DYHeaderRulerView
  299. if headerView == nil{
  300. headerView = DYHeaderRulerView.init(frame: CGRect.init(x: 0, y: 0, width: Int(self.frame.size.width/2), height: CollectionHeight))
  301. headerView!.backgroundColor = UIColor.clear
  302. headerView!.headerMinValue = Int(minValue)
  303. headerView!.headerUnit = rulerUnit
  304. headerView!.tag = 1000
  305. cell.contentView.addSubview(headerView!)
  306. }
  307. return cell
  308. }else if indexPath.item == stepNum+1 {
  309. let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "footerCell", for: indexPath)
  310. var footerView:DYFooterRulerView? = cell.contentView.viewWithTag(1001) as? DYFooterRulerView
  311. if footerView == nil {
  312. footerView = DYFooterRulerView.init(frame: CGRect.init(x: 0, y: 0, width: Int(self.frame.size.width/2), height: CollectionHeight))
  313. footerView!.backgroundColor = UIColor.clear
  314. footerView!.footerMaxValue = Int(maxValue)
  315. footerView!.footerUnit = rulerUnit
  316. footerView!.tag = 1001
  317. cell.contentView.addSubview(footerView!)
  318. }
  319. return cell
  320. }else{
  321. let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "customeCell", for: indexPath)
  322. var rulerView:DYRulerView? = cell.contentView.viewWithTag(1002) as? DYRulerView
  323. if rulerView == nil {
  324. rulerView = DYRulerView.init(frame: CGRect.init(x: 0, y: 0, width: RulerGap*betweenNum, height: CollectionHeight))
  325. rulerView!.backgroundColor = UIColor.clear
  326. rulerView!.step = step
  327. rulerView!.unit = rulerUnit
  328. rulerView!.tag = 1002
  329. rulerView!.betweenNumber = betweenNum;
  330. cell.contentView.addSubview(rulerView!)
  331. }
  332. rulerView?.backgroundColor = .clear
  333. // if indexPath.item >= 8 && indexPath.item <= 12{
  334. // rulerView?.backgroundColor = UIColor.green
  335. // }else if(indexPath.item >= 13 && indexPath.item <= 18){
  336. // rulerView?.backgroundColor = UIColor.red
  337. // }else{
  338. // rulerView?.backgroundColor = UIColor.gray
  339. // }
  340. rulerView!.minValue = step*Float((indexPath.item-1))*Float(betweenNum)+minValue
  341. rulerView!.maxValue = step*Float(indexPath.item)*Float(betweenNum)
  342. rulerView!.setNeedsDisplay()
  343. return cell
  344. }
  345. }
  346. }
  347. extension DYScrollRulerView:UICollectionViewDelegate{
  348. func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  349. }
  350. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  351. let value = Int(scrollView.contentOffset.x)/RulerGap
  352. let totalValue = Float(value)*step+minValue
  353. if scrollByHand {
  354. if totalValue>=maxValue {
  355. lazyValueTF.text = String.init(format: "%.1f", maxValue)
  356. }else if totalValue <= minValue {
  357. lazyValueTF.text = String.init(format: "%.1f", minValue)
  358. }else{
  359. lazyValueTF.text = String.init(format: "%.1f", Float(value)*step+minValue)
  360. }
  361. }
  362. delegate?.dyScrollRulerViewValueChange(rulerView: self, value: totalValue)
  363. }
  364. func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
  365. if !decelerate {
  366. self.setRealValueAndAnimated(realValue: Float(scrollView.contentOffset.x)/Float(RulerGap), animated: true)
  367. }
  368. }
  369. func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
  370. self.setRealValueAndAnimated(realValue: Float(scrollView.contentOffset.x)/Float(RulerGap), animated: true)
  371. }
  372. }
  373. extension DYScrollRulerView:UICollectionViewDelegateFlowLayout{
  374. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  375. if indexPath.item == 0 || indexPath.item == stepNum + 1 {
  376. return CGSize(width: Int(self.frame.size.width/2), height: CollectionHeight)
  377. }
  378. return CGSize(width: RulerGap*betweenNum, height: CollectionHeight)
  379. }
  380. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
  381. return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
  382. }
  383. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  384. return 0
  385. }
  386. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  387. return 0
  388. }
  389. }
  390. extension DYScrollRulerView:UITextFieldDelegate{
  391. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  392. self.editDone()
  393. return true
  394. }
  395. }