Skip to content

Instantly share code, notes, and snippets.

@hamsternik
Forked from daryadariaa/Cell.swift
Last active November 5, 2019 10:44
Show Gist options
  • Save hamsternik/eff9dbf1416e885dd6ea2fc35aa3f5c0 to your computer and use it in GitHub Desktop.
Save hamsternik/eff9dbf1416e885dd6ea2fc35aa3f5c0 to your computer and use it in GitHub Desktop.
import UIKit
import RxSwift
import RxCocoa
class AddDiscountTableViewCell: UITableViewCell {
@IBOutlet weak var discountTypeDropDown: SelectionDropDownView!
@IBOutlet weak var amountTextField: PrimaryTextField!
@IBOutlet weak var itemsDropDown: SelectionDropDownView!
static var identifier = "AddDiscountTableViewCell"
private var disposeBag = DisposeBag()
override func awakeFromNib() {
super.awakeFromNib()
configureView()
bind()
}
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
private func configureView() {
discountTypeDropDown.placeholder = "discount".localized()
amountTextField.placeholder = "amount".localized()
}
private func bind() {
}
}
import UIKit
import RxSwift
import RxCocoa
import MaterialComponents
protocol SelectionDropDownViewDelegate: class {
func didSelectItem(dropDown: SelectionDropDownView, item: DropdownItem)
func didDeselectItem(dropDown: SelectionDropDownView, item: DropdownItem)
}
enum SelectionDropDownType {
case `default`
case checkmark
}
class SelectionDropDownView: UIView {
private struct Constants {
static let smallPlaceholderFontSize: CGFloat = 12
static let bigPlaceholderFontSize: CGFloat = 16
static let leftRightMargin: CGFloat = 12
static let topBottomMargin: CGFloat = 8
}
private let disposeBag = DisposeBag()
private let smallPlaceholderLabel = UILabel()
private let bigPlaceholderLabel = UILabel()
private let valueLabel = UILabel()
private let bottomLineView = UIView()
private let dismissGesture = UITapGestureRecognizer()
private let optionsViewController = DropdownListTableViewController.storyboardViewController()
fileprivate let openSubject = PublishSubject<Void>()
var type: SelectionDropDownType = .default {
didSet {
optionsViewController.type = type
}
}
var placeholder: String? {
didSet {
smallPlaceholderLabel.text = placeholder
bigPlaceholderLabel.text = placeholder
}
}
var value: String? {
didSet {
valueLabel.text = value
valueLabel.isHidden = value == nil
smallPlaceholderLabel.isHidden = value == nil
bigPlaceholderLabel.isHidden = value != nil
}
}
var selectedItem: DropdownItem? {
get {
return selectedItems.first
}
set {
if let item = newValue, type == .default {
selectedItems.removeAll()
selectedItems.append(item)
}
}
}
var selectedItems = [DropdownItem]() {
didSet {
switch type {
case .default:
value = selectedItems.first?.title
case .checkmark:
if selectedItems.count > 1 {
value = String(format: "items-count".localized(), NSNumber(value: selectedItems.count));
} else {
value = String(format: "item-count".localized(), NSNumber(value: selectedItems.count));
}
}
}
}
weak var delegate: SelectionDropDownViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func present(in viewController: UIViewController, options: [DropdownItem]) {
guard !options.isEmpty else {
return
}
bottomLineView.backgroundColor = .primary
optionsViewController.items = options
optionsViewController.selection = selectedItems
viewController.present(optionsViewController, animated: true)
}
private func commonInit() {
dismissGesture.delegate = self
optionsViewController.transitioningDelegate = self
optionsViewController.modalPresentationStyle = .custom
optionsViewController.delegate = self
configure()
bind()
}
private func configure() {
backgroundColor = .surface
layer.masksToBounds = false
layer.cornerRadius = AppearenceConfig.cornerRadius
layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
smallPlaceholderLabel.font = .systemFont(ofSize: Constants.smallPlaceholderFontSize)
smallPlaceholderLabel.textColor = .textPlaceholder
smallPlaceholderLabel.isHidden = true
bigPlaceholderLabel.font = .systemFont(ofSize: Constants.bigPlaceholderFontSize)
bigPlaceholderLabel.textColor = .textPlaceholder
valueLabel.font = .systemFont(ofSize: Constants.bigPlaceholderFontSize)
valueLabel.textColor = .text
valueLabel.isHidden = true
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.addArrangedSubview(smallPlaceholderLabel)
stackView.addArrangedSubview(bigPlaceholderLabel)
stackView.addArrangedSubview(valueLabel)
addSubview(stackView)
stackView.leftAnchor.constraint(equalTo: leftAnchor, constant: Constants.leftRightMargin).isActive = true
stackView.topAnchor.constraint(equalTo: topAnchor, constant: Constants.topBottomMargin).isActive = true
stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -Constants.topBottomMargin).isActive = true
let arrowImageView = UIImageView(image: UIImage(named: "arrowDown"))
arrowImageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(arrowImageView)
arrowImageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
arrowImageView.rightAnchor.constraint(equalTo: rightAnchor, constant: -Constants.leftRightMargin).isActive = true
bottomLineView.translatesAutoresizingMaskIntoConstraints = false
bottomLineView.backgroundColor = .blueShadow
addSubview(bottomLineView)
bottomLineView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
bottomLineView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
bottomLineView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
bottomLineView.heightAnchor.constraint(equalToConstant: 1).isActive = true
}
private func bind() {
dismissGesture.rx.event.subscribe(onNext: { [unowned self] _ in
self.bottomLineView.backgroundColor = .blueShadow
self.optionsViewController.dismiss(animated: true)
}).disposed(by: disposeBag)
let tap = UITapGestureRecognizer()
addGestureRecognizer(tap)
tap.rx.event.subscribe(onNext: { [unowned self] gesture in
self.openSubject.onNext(())
}).disposed(by: disposeBag)
}
}
extension SelectionDropDownView: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
guard presented is DropdownListTableViewController else {
return nil
}
return DropdownPresentAnimation(action: .show, sourceView: self, dismissGesture: dismissGesture)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return DropdownPresentAnimation(action: .hide, sourceView: self, dismissGesture: dismissGesture)
}
}
extension SelectionDropDownView: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let location = touch.location(in: optionsViewController.view)
return !optionsViewController.view.bounds.contains(location)
}
}
extension SelectionDropDownView: DropdownListTableViewControllerDelegate {
func didSelect(item: DropdownItem) {
switch type {
case .default:
selectedItems.removeAll()
selectedItems.append(item)
delegate?.didSelectItem(dropDown: self, item: item)
optionsViewController.dismiss(animated: true)
case .checkmark:
if !selectedItems.contains(item) && item.checked {
selectedItems.append(item)
delegate?.didSelectItem(dropDown: self, item: item)
} else {
selectedItems.removeAll(where: { $0 == item })
delegate?.didDeselectItem(dropDown: self, item: item)
}
}
bottomLineView.backgroundColor = .blueShadow
}
}
extension Reactive where Base: SelectionDropDownView {
var tap: ControlEvent<Void> {
return ControlEvent(events: base.openSubject)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment