Advertisement
Guest User

Untitled

a guest
Feb 25th, 2020
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.33 KB | None | 0 0
  1. //
  2. // CustomPickerView.swift
  3. // ARIUIKit
  4. //
  5. // Created by ait belarbi mohamed amine on 17/01/2020.
  6. //
  7.  
  8. import UIKit
  9.  
  10. public struct PickerViewStyle {
  11. let name, type: String?
  12. let textStyleLabel, textStyleHelp, textStyleInput, textStyleFeedback: TextStyleByStates?
  13. let radius: [CGFloat]?
  14. let states: InputStyleByState?
  15.  
  16. public init(name: String?,
  17. type: String?,
  18. textStyleLabel: TextStyleByStates?,
  19. textStyleHelp: TextStyleByStates?,
  20. textStyleInput: TextStyleByStates?,
  21. textStyleFeedback: TextStyleByStates?,
  22. radius: [CGFloat]?,
  23. states: InputStyleByState? ) {
  24. self.name = name
  25. self.type = type
  26. self.textStyleLabel = textStyleLabel
  27. self.textStyleHelp = textStyleHelp
  28. self.textStyleInput = textStyleInput
  29. self.textStyleFeedback = textStyleFeedback
  30. self.radius = radius
  31. self.states = states
  32. }
  33. }
  34.  
  35. public struct CustomPickerViewModel {
  36. let id: String
  37. let required: Bool?
  38. let title, helpTitle, prefill: String?
  39. var items: [ComponentItemsViewModel]?
  40. let autovalidate: Bool?
  41. let style: PickerViewStyle?
  42. let pickerType: ComponentTypeViewModel?
  43. let onAutoValidate: (() -> ())?
  44. var state: InputState?
  45.  
  46. public init(id: String,
  47. required: Bool?,
  48. title: String?,
  49. helpTitle: String?,
  50. prefill: String?,
  51. items: [ComponentItemsViewModel]?,
  52. pickerViewStyle: PickerViewStyle?,
  53. pickerType: ComponentTypeViewModel? = .text,
  54. autovalidate: Bool?,
  55. state: InputState = .empty,
  56. onAutoValidate: (() -> ())? = nil) {
  57. self.id = id
  58. self.required = required
  59. self.title = title
  60. self.helpTitle = helpTitle
  61. self.prefill = prefill
  62. self.items = items
  63. self.style = pickerViewStyle
  64. self.pickerType = pickerType
  65. self.autovalidate = autovalidate
  66. self.state = state
  67. self.onAutoValidate = onAutoValidate
  68. }
  69. }
  70.  
  71. public final class CustomPickerView: UIView {
  72.  
  73. static let identifier = String(describing: CustomPickerView.self)
  74.  
  75. @IBOutlet private weak var helpLabel: UILabel!
  76. @IBOutlet private weak var titleLabel: UILabel!
  77. @IBOutlet private weak var arrowImageView: UIImageView! {
  78. didSet {
  79. arrowImageView.image = UIImage.tinyArrowDown
  80. }
  81. }
  82. @IBOutlet private weak var containerView: UIView!
  83. @IBOutlet private weak var currentValueLabel: UILabel!
  84. @IBOutlet private weak var helpLabelContainerView: UIView!
  85. @IBOutlet private weak var titleLabelContainerView: UIView!
  86.  
  87. public var listContainer = UITextField(frame: .zero)
  88. public var currentValue: String {
  89. get {
  90. let prefillData = viewModel?.pickerType == .date ? currentValueLabel.text : viewModel.items?.filter { $0.selected == true }.first?.value
  91. return prefillData ?? ""
  92. }
  93. }
  94. public var viewModel: CustomPickerViewModel! {
  95. didSet {
  96. updateUI()
  97. }
  98. }
  99.  
  100. required public init?(coder aDecoder: NSCoder) {
  101. super.init(coder: aDecoder)
  102. loadNib()
  103. }
  104.  
  105. public init() {
  106. super.init(frame: .zero)
  107. loadNib()
  108. }
  109.  
  110. private func loadNib() {
  111. let nib = UINib(nibName: CustomPickerView.identifier, bundle: ARIUIKit.bundle)
  112. guard let contentView = nib.instantiate(withOwner: self, options: nil).first as? UIView else {
  113. return
  114. }
  115. addSubview(contentView)
  116. contentView.translatesAutoresizingMaskIntoConstraints = false
  117. contentView.layoutAttachAll(to: self)
  118. }
  119.  
  120. public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  121. super.touchesBegan(touches, with: event)
  122. setInputStyleBy(inputEvent: .highlight)
  123. }
  124.  
  125. public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
  126. super.touchesEnded(touches, with: event)
  127. toucheEnded(touches: touches)
  128. }
  129.  
  130. public override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
  131. super.touchesCancelled(touches, with: event)
  132. toucheEnded(touches: touches)
  133. }
  134.  
  135. private func toucheEnded(touches: Set<UITouch>) {
  136. setInputStyleBy(inputEvent: .default)
  137. listContainer.becomeFirstResponder()
  138. }
  139.  
  140. public func showError() {
  141. viewModel.state = .error
  142. }
  143.  
  144. private func updateUI() {
  145. helpLabelContainerView.isHidden = viewModel?.helpTitle?.isEmpty ?? true ? true : false
  146. helpLabel.text = viewModel?.helpTitle
  147. titleLabel.text = viewModel?.title
  148. currentValueLabel.text = viewModel.items?.filter { $0.selected == true }.first?.label ?? viewModel?.prefill
  149. setInputStyle()
  150. setCornerRadius()
  151. setInputStyleBy(inputEvent: .default)
  152. initPickerView(type: (viewModel?.pickerType ?? .text))
  153. listContainer.delegate = self
  154. }
  155.  
  156. private func setCornerRadius() {
  157. var corners: UIRectCorner = []
  158. var radius: CGFloat = 0.0
  159. if let topLeftCorner = viewModel.style?.radius?[0], topLeftCorner > 0 {
  160. corners.insert(.topLeft)
  161. radius = topLeftCorner
  162. }
  163. if let topRightCorner = viewModel.style?.radius?[1], topRightCorner > 0 {
  164. corners.insert(.topRight)
  165. radius = topRightCorner
  166. }
  167. if let bottomLeftCorner = viewModel.style?.radius?[2], bottomLeftCorner > 0 {
  168. corners.insert(.bottomLeft)
  169. radius = bottomLeftCorner
  170. }
  171. if let bottomRighttCorner = viewModel.style?.radius?[3], bottomRighttCorner > 0 {
  172. corners.insert(.bottomRight)
  173. radius = bottomRighttCorner
  174. }
  175. containerView.roundCorners(corners, radius: radius)
  176. }
  177.  
  178. private func initPickerView(type: ComponentTypeViewModel) {
  179. if type == .date {
  180. let datePicker: UIDatePicker = UIDatePicker()
  181. datePicker.datePickerMode = .date
  182. if let strDate = viewModel.title {
  183. let dateFormatter = ISO8601DateFormatter()
  184. dateFormatter.formatOptions = [.withFullDate]
  185. if let date = dateFormatter.date(from: strDate) {
  186. datePicker.date = date
  187. }
  188. }
  189. datePicker.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged)
  190. listContainer.inputView = datePicker
  191. } else {
  192. let listPicker: UIPickerView = UIPickerView()
  193. listPicker.dataSource = self
  194. listPicker.delegate = self
  195. listContainer.inputView = listPicker
  196. }
  197. self.addSubview(listContainer)
  198. }
  199.  
  200. @objc func dateChanged(_ sender: UIDatePicker) {
  201. let dateFormatter = ISO8601DateFormatter()
  202. dateFormatter.formatOptions = [.withFullDate]
  203. let strDate = dateFormatter.string(from: sender.date)
  204. currentValueLabel.text = strDate
  205. }
  206.  
  207. private func setInputStyle() {
  208. var textStyleLabel: TextStyle?
  209. var textStyleInput: TextStyle?
  210. var textStyleHelp: TextStyle?
  211. var textStyleFeedback: TextStyle?
  212. switch viewModel.state {
  213. case .default:
  214. textStyleInput = viewModel.style?.textStyleInput?.default
  215. textStyleLabel = viewModel.style?.textStyleLabel?.default
  216. textStyleHelp = viewModel.style?.textStyleHelp?.default
  217. textStyleFeedback = viewModel.style?.textStyleFeedback?.default
  218. case .success:
  219. textStyleInput = viewModel.style?.textStyleInput?.success
  220. textStyleLabel = viewModel.style?.textStyleLabel?.success
  221. textStyleHelp = viewModel.style?.textStyleHelp?.success
  222. textStyleFeedback = viewModel.style?.textStyleFeedback?.success
  223. case .empty:
  224. textStyleInput = viewModel.style?.textStyleInput?.empty
  225. textStyleLabel = viewModel.style?.textStyleLabel?.empty
  226. textStyleHelp = viewModel.style?.textStyleHelp?.empty
  227. textStyleFeedback = viewModel.style?.textStyleFeedback?.empty
  228. case .error:
  229. textStyleInput = viewModel.style?.textStyleInput?.error
  230. textStyleLabel = viewModel.style?.textStyleLabel?.error
  231. textStyleHelp = viewModel.style?.textStyleHelp?.error
  232. textStyleFeedback = viewModel.style?.textStyleFeedback?.error
  233. case .none:
  234. break
  235. }
  236. if let textStyle = textStyleLabel {
  237. titleLabel.setStyle(textStyle)
  238. }
  239. if let textStyle = textStyleHelp {
  240. helpLabel.setStyle(textStyle)
  241. }
  242. if let textStyle = textStyleInput {
  243. currentValueLabel.setStyle(textStyle)
  244. }
  245. }
  246.  
  247. private func setInputStyleBy(inputEvent: InputEvent) {
  248. switch viewModel.state {
  249. case .default:
  250. if let df = viewModel.style?.states?.default {
  251. setInputStyle(inputStyleByEvent: df, inputEvent: inputEvent)
  252. }
  253. case .success:
  254. if let success = viewModel.style?.states?.success {
  255. setInputStyle(inputStyleByEvent: success, inputEvent: inputEvent)
  256. }
  257. case .empty:
  258. if let empty = viewModel.style?.states?.empty {
  259. setInputStyle(inputStyleByEvent: empty, inputEvent: inputEvent)
  260. }
  261. case .error:
  262. if let error = viewModel.style?.states?.error {
  263. setInputStyle(inputStyleByEvent: error, inputEvent: inputEvent)
  264. }
  265. case .none:
  266. break
  267. }
  268. }
  269.  
  270. private func setInputStyle(inputStyleByEvent: InputStyleByEvent, inputEvent: InputEvent) {
  271. switch inputEvent {
  272. case .default:
  273. if let background = inputStyleByEvent.default?.background {
  274. setInputBackground(style: background)
  275. }
  276. case .highlight:
  277. if let background = inputStyleByEvent.highlight?.background {
  278. setInputBackground(style: background)
  279. }
  280. case .selected:
  281. if let background = inputStyleByEvent.selected?.background {
  282. setInputBackground(style: background)
  283. }
  284. }
  285. }
  286.  
  287. private func setInputBackground(style: BackgroundStyle) {
  288. switch style.fill?.type {
  289. case .solid:
  290. containerView.backgroundColor = style.fill?.colors?.first ?? .white
  291. case .gradient:
  292. if let firstColor = style.fill?.colors?[0],
  293. let secondColor = style.fill?.colors?[1] {
  294. containerView.removeGradientBackgroundIfNeeded()
  295. containerView.addGradientBackground(direction: .leftToRight, color1: firstColor, color2: secondColor)
  296. }
  297. case .none:
  298. break
  299. }
  300. }
  301. }
  302.  
  303. extension CustomPickerView: UITextFieldDelegate {
  304. public func textFieldDidEndEditing(_ textField: UITextField) {
  305. if viewModel?.autovalidate == true, let onAutoValidate = viewModel?.onAutoValidate {
  306. onAutoValidate()
  307. }
  308. }
  309. }
  310.  
  311. extension CustomPickerView: UIPickerViewDelegate, UIPickerViewDataSource {
  312. public func numberOfComponents(in pickerView: UIPickerView) -> Int {
  313. return 1
  314. }
  315.  
  316. public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
  317. return viewModel?.items?.count ?? 0
  318. }
  319.  
  320. public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
  321. return viewModel?.items?[row].label
  322. }
  323.  
  324. public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
  325. currentValueLabel.text = viewModel?.items?[row].label
  326. var selectedIndex: Int = 0
  327. var i: Int = 0
  328. viewModel.items?.forEach {
  329. if $0.selected == true {
  330. selectedIndex = i
  331. return
  332. }
  333. i += 1
  334. }
  335. viewModel?.items?[selectedIndex].selected = false
  336. viewModel?.items?[row].selected = true
  337. }
  338. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement