Last active
October 17, 2019 11:14
-
-
Save anirudhamahale/6930693b0a69a1d239a3efc58b1ed9e8 to your computer and use it in GitHub Desktop.
Swift UIPickerView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PickerView.swift | |
// SlideUpAnimation | |
// | |
// Created by Anirudha Mahale on 17/10/19. | |
// Copyright © 2019 Anirudha Mahale. All rights reserved. | |
// | |
import UIKit | |
import RxSwift | |
import RxCocoa | |
import RxGesture | |
@IBDesignable | |
class PickerView: UIView { | |
deinit { | |
print("PickerView 🔥") | |
} | |
@IBInspectable var pickerBackgroundColor: UIColor = UIColor.white { | |
didSet { | |
self.pickerControllerBackgroundView.backgroundColor = pickerBackgroundColor | |
} | |
} | |
lazy var pickerController: UIPickerView = { | |
let pickerView = UIPickerView() | |
pickerView.translatesAutoresizingMaskIntoConstraints = false | |
pickerView.dataSource = self | |
pickerView.delegate = self | |
return pickerView | |
}() | |
lazy var pickerControllerBackgroundView: UIView = { | |
let view = UIView() | |
view.isUserInteractionEnabled = true | |
view.translatesAutoresizingMaskIntoConstraints = false | |
return view | |
}() | |
lazy var doneButton: UIButton = { | |
let doneButton = UIButton(type: UIButtonType.custom) | |
doneButton.setTitle("Done", for: .normal) | |
doneButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20) | |
doneButton.translatesAutoresizingMaskIntoConstraints = false | |
doneButton.rx | |
.tap | |
.subscribe(onNext: { [weak self] _ in | |
guard let `self` = self else { return } | |
let string = self.data[self.selectedIndex] | |
self.didSelectSubject.onNext(string) | |
self.hide() | |
}).disposed(by: disposeBag) | |
return doneButton | |
}() | |
lazy var cancelButton: UIButton = { | |
let cancelButton = UIButton(type: UIButtonType.custom) | |
cancelButton.setTitle("Cancel", for: .normal) | |
cancelButton.translatesAutoresizingMaskIntoConstraints = false | |
cancelButton.rx | |
.tap | |
.subscribe(onNext: { [weak self] _ in | |
self?.hide() | |
}).disposed(by: disposeBag) | |
return cancelButton | |
}() | |
private var data = [String]() | |
private var screenSize: CGRect { | |
return UIScreen.main.bounds | |
} | |
private var bottomPadding: CGFloat = 0.0 | |
private let didSelectSubject = PublishSubject<String>() | |
private var selectedIndex = 0 | |
var didSelect: Observable<String> { | |
return didSelectSubject.asObservable() | |
} | |
let disposeBag = DisposeBag() | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
if #available(iOS 11.0, *) { | |
let window = UIApplication.shared.keyWindow | |
bottomPadding = window?.safeAreaInsets.bottom ?? 0 | |
} | |
setupViews() | |
} | |
private func setupViews() { | |
setUpPickerBackgroundView() | |
setToolbar() | |
setUpPickerView() | |
self.layoutIfNeeded() | |
self.rx | |
.tapGesture(configuration: { (_, delegate) in | |
delegate.simultaneousRecognitionPolicy = .never | |
}) | |
.when(.recognized) | |
.subscribe(onNext: { [weak self] _ in | |
self?.hide() | |
}).disposed(by: disposeBag) | |
} | |
private func setUpPickerBackgroundView() { | |
self.addSubview(pickerControllerBackgroundView) | |
NSLayoutConstraint.activate([pickerControllerBackgroundView.leadingAnchor.constraint(equalTo: self.leadingAnchor), | |
pickerControllerBackgroundView.trailingAnchor.constraint(equalTo: self.trailingAnchor), | |
pickerControllerBackgroundView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -bottomPadding), | |
]) | |
} | |
private func setUpPickerView() { | |
pickerControllerBackgroundView.addSubview(pickerController) | |
NSLayoutConstraint.activate([pickerController.topAnchor.constraint(equalTo: doneButton.bottomAnchor), | |
pickerController.leadingAnchor.constraint(equalTo: pickerControllerBackgroundView.leadingAnchor), | |
pickerController.trailingAnchor.constraint(equalTo: pickerControllerBackgroundView.trailingAnchor), | |
pickerController.bottomAnchor.constraint(equalTo: pickerControllerBackgroundView.bottomAnchor)]) | |
} | |
private func setToolbar() { | |
let buttonBackgroundView = UIView() | |
buttonBackgroundView.translatesAutoresizingMaskIntoConstraints = false | |
buttonBackgroundView.backgroundColor = .red | |
pickerControllerBackgroundView.addSubview(buttonBackgroundView) | |
pickerControllerBackgroundView.addSubview(doneButton) | |
NSLayoutConstraint.activate([doneButton.trailingAnchor.constraint(equalTo: pickerControllerBackgroundView.trailingAnchor, constant: -16), | |
doneButton.topAnchor.constraint(equalTo: pickerControllerBackgroundView.topAnchor)]) | |
pickerControllerBackgroundView.addSubview(cancelButton) | |
NSLayoutConstraint.activate([cancelButton.leadingAnchor.constraint(equalTo: pickerControllerBackgroundView.leadingAnchor, constant: 16), | |
cancelButton.topAnchor.constraint(equalTo: pickerControllerBackgroundView.topAnchor)]) | |
NSLayoutConstraint.activate([buttonBackgroundView.leadingAnchor.constraint(equalTo: pickerControllerBackgroundView.leadingAnchor), | |
buttonBackgroundView.topAnchor.constraint(equalTo: pickerControllerBackgroundView.topAnchor), | |
buttonBackgroundView.bottomAnchor.constraint(equalTo: doneButton.bottomAnchor), | |
buttonBackgroundView.trailingAnchor.constraint(equalTo: pickerControllerBackgroundView.trailingAnchor)]) | |
} | |
} | |
// MARK:- PUBLIC METHODS | |
extension PickerView { | |
func show(with data: [String], animated: Bool? = true) { | |
self.data = data | |
guard let window = UIApplication.shared.keyWindow else { return } | |
self.backgroundColor = UIColor.black.withAlphaComponent(0.1) | |
self.frame = UIScreen.main.bounds | |
self.alpha = 0 | |
window.addSubview(self) | |
pickerControllerBackgroundView.transform = CGAffineTransform(translationX: 0, y: screenSize.height) | |
if animated == true { | |
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .curveEaseInOut, animations: { | |
self.alpha = 1.0 | |
self.pickerControllerBackgroundView.transform = CGAffineTransform.identity | |
}, completion: nil) | |
} else { | |
self.alpha = 0.5 | |
self.pickerControllerBackgroundView.transform = CGAffineTransform.identity | |
} | |
} | |
func hide(animated: Bool? = true) { | |
UIView.animate(withDuration: 0.5, animations: { | |
self.alpha = 0 | |
self.pickerControllerBackgroundView.transform = CGAffineTransform(translationX: 0, y: self.screenSize.height) | |
}, completion: { _ in | |
self.removeFromSuperview() | |
}) | |
} | |
} | |
extension PickerView: UIPickerViewDataSource { | |
func numberOfComponents(in pickerView: UIPickerView) -> Int { | |
1 | |
} | |
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { | |
return data.count | |
} | |
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { | |
return data[row] | |
} | |
} | |
extension PickerView: UIPickerViewDelegate { | |
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { | |
selectedIndex = row | |
} | |
} |
Author
anirudhamahale
commented
Oct 17, 2019
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment