Skip to content

Instantly share code, notes, and snippets.

@anirudhamahale
Last active October 17, 2019 11:14
Show Gist options
  • Save anirudhamahale/6930693b0a69a1d239a3efc58b1ed9e8 to your computer and use it in GitHub Desktop.
Save anirudhamahale/6930693b0a69a1d239a3efc58b1ed9e8 to your computer and use it in GitHub Desktop.
Swift UIPickerView
//
// 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
}
}
@anirudhamahale
Copy link
Author

anirudhamahale commented Oct 17, 2019

import UIKit
import RxSwift

class ViewController: UIViewController {
  
  let disposeBag = DisposeBag()
  
  @IBAction func onClickMenu(_ sender: Any) {
    let pickerController = PickerView()
    pickerController.didSelect
      .subscribe(onNext: { value in
        print(value)
      }).disposed(by: disposeBag)
    let settingArray = ["Profile","Favorite","Notification","Change Password","Logout"]
    pickerController.pickerBackgroundColor = .green
    pickerController.show(with: settingArray)
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment