Skip to content

Instantly share code, notes, and snippets.

@sk-chanch
Last active October 27, 2020 04:49
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save sk-chanch/308c55ded9a099d05f2309a0209ce143 to your computer and use it in GitHub Desktop.
Simple Star Rating for swift
//
// CustomRatingView.swift
// AppStarterKit
//
// Created by MAC-KHUAD on 26/10/2563 BE.
// Copyright © 2563 megazy. All rights reserved.
//
import UIKit
import RxSwift
import RxGesture
import SnapKit
class CustomRatingView: UIView {
@IBInspectable var numberOfStar:CGFloat = 5{
didSet{
setupInit()
}
}
@IBInspectable var starEmptyColor:UIColor = #colorLiteral(red: 0.9019607843, green: 0.9019607843, blue: 0.9019607843, alpha: 1){
didSet{
update()
}
}
@IBInspectable var starFillColor:UIColor = #colorLiteral(red: 0.968627451, green: 0.6745098039, blue: 0.08235294118, alpha: 1){
didSet{
update()
}
}
@IBInspectable var starRating:Int = 3{
didSet{
update()
// debugLog.info(with: starRating)
}
}
private var stackView:UIStackView!
@IBInspectable var spacing:CGFloat = 8{
didSet{
update()
}
}
private var disposeBag = DisposeBag()
// private let debugLog = Log()
override init(frame: CGRect) {
super.init(frame: frame)
setupInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupInit()
}
private func setupInit(){
stackView?.removeFromSuperview()
stackView = createStackView()
addSubview(stackView)
binding()
}
override func layoutSubviews() {
stackView?.snp.remakeConstraints{make in
make.height.equalTo(snp.height)
make.leading.equalToSuperview().offset(spacing)
make.trailing.equalToSuperview().offset(-spacing)
make.top.bottom.equalToSuperview()
}
}
private func createStackView()->UIStackView{
let stackView = UIStackView()
stackView.alignment = .fill
stackView.axis = .horizontal
stackView.spacing = spacing
stackView.distribution = .fillEqually
(0...(Int(numberOfStar) - 1)).forEach{ i in
let starImg = #imageLiteral(resourceName: "ic_star").withRenderingMode(.alwaysTemplate)
let imgView = UIImageView(image:starImg)
imgView.contentMode = .scaleAspectFit
imgView.tintColor = i < starRating ? starFillColor : starEmptyColor
stackView.addArrangedSubview(imgView)
imgView.tag = i
}
return stackView
}
private func update(){
stackView?.arrangedSubviews.enumerated().forEach{ index, v in
v.tintColor = index < starRating ? starFillColor : starEmptyColor
}
stackView.spacing = spacing
}
private func binding(){
disposeBag = DisposeBag()
stackView?.rx.anyGesture(.tap(), .pan())
.observeOn(MainScheduler.instance)
.filter{$0.state == .changed || $0.state == .ended}
.asLocation(in: .view)
.map{[weak self] in ($0, self?.stackView?.arrangedSubviews ?? [])}
.map{lo,v in (v.lazy.filter{lo.x > $0.frame.origin.x}.last.map{$0.tag} ?? 0) + 1}
.distinctUntilChanged()
.subscribe(onNext:{[weak self] r in
self?.starRating = r
self?.update()
}).disposed(by: disposeBag)
}
// deinit {
// debugLog.deInit(controller: self)
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment