Skip to content

Commit

Permalink
feat: [#9] Price Slider 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
ghis22130 committed Jun 1, 2021
1 parent 076a37e commit 545e133
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 7 deletions.
20 changes: 20 additions & 0 deletions iOS/Arirbnb/Arirbnb.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
FFCA98CA2665CD360057ADDD /* SearchFlowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCA98C72665CD360057ADDD /* SearchFlowView.swift */; };
FFCA98CB2665CD360057ADDD /* FilteringCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FFCA98C82665CD360057ADDD /* FilteringCell.xib */; };
FFCA98CD2665CD460057ADDD /* FilterItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCA98CC2665CD460057ADDD /* FilterItems.swift */; };
FFCA98D02665DE0D0057ADDD /* DumbaSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCA98CF2665DE0D0057ADDD /* DumbaSlider.swift */; };
FFCA98D22665DE2B0057ADDD /* SliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCA98D12665DE2B0057ADDD /* SliderView.swift */; };
FFCA98D42665E2570057ADDD /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCA98D32665E2570057ADDD /* UIView+Extension.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -115,6 +118,9 @@
FFCA98C72665CD360057ADDD /* SearchFlowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchFlowView.swift; sourceTree = "<group>"; };
FFCA98C82665CD360057ADDD /* FilteringCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FilteringCell.xib; sourceTree = "<group>"; };
FFCA98CC2665CD460057ADDD /* FilterItems.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterItems.swift; sourceTree = "<group>"; };
FFCA98CF2665DE0D0057ADDD /* DumbaSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DumbaSlider.swift; sourceTree = "<group>"; };
FFCA98D12665DE2B0057ADDD /* SliderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderView.swift; sourceTree = "<group>"; };
FFCA98D32665E2570057ADDD /* UIView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -374,6 +380,7 @@
FFCA98B52665CCCE0057ADDD /* View */ = {
isa = PBXGroup;
children = (
FFCA98CE2665DE030057ADDD /* Slider */,
FFCA98C62665CD360057ADDD /* FilteringCell.swift */,
FFCA98C82665CD360057ADDD /* FilteringCell.xib */,
FFCA98C72665CD360057ADDD /* SearchFlowView.swift */,
Expand All @@ -400,10 +407,20 @@
FFCA98BF2665CD1F0057ADDD /* Day+Extension.swift */,
FFCA98C02665CD1F0057ADDD /* NotificationName.swift */,
FFCA98C12665CD1F0057ADDD /* UserInfoKey.swift */,
FFCA98D32665E2570057ADDD /* UIView+Extension.swift */,
);
path = Extension;
sourceTree = "<group>";
};
FFCA98CE2665DE030057ADDD /* Slider */ = {
isa = PBXGroup;
children = (
FFCA98CF2665DE0D0057ADDD /* DumbaSlider.swift */,
FFCA98D12665DE2B0057ADDD /* SliderView.swift */,
);
path = Slider;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -561,6 +578,7 @@
FFAB2ACD26620C4A008AEB31 /* ReuseIdentifierable.swift in Sources */,
FF5767CF2653A2AE00F46A43 /* WishListViewController.swift in Sources */,
FF665D1D26574E4200130ABB /* SearchResultCell.swift in Sources */,
FFCA98D22665DE2B0057ADDD /* SliderView.swift in Sources */,
FF665D302657845700130ABB /* UIImageView+Extension.swift in Sources */,
FF5767B42653311E00F46A43 /* ThemeDestinationsCell.swift in Sources */,
FFCA98C52665CD1F0057ADDD /* UserInfoKey.swift in Sources */,
Expand All @@ -569,7 +587,9 @@
FF5767672652490C00F46A43 /* MainSearchViewController.swift in Sources */,
FFCA98CA2665CD360057ADDD /* SearchFlowView.swift in Sources */,
FF5767632652490C00F46A43 /* AppDelegate.swift in Sources */,
FFCA98D42665E2570057ADDD /* UIView+Extension.swift in Sources */,
FFCA98BB2665CCE70057ADDD /* DayLabel.swift in Sources */,
FFCA98D02665DE0D0057ADDD /* DumbaSlider.swift in Sources */,
FFAB2AD126620E5F008AEB31 /* UINibCreateable.swift in Sources */,
FFCA98B42665CCB90057ADDD /* SearchFilteringViewController.swift in Sources */,
FF5767D52653A99400F46A43 /* MyReserVationViewModel.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions iOS/Arirbnb/Arirbnb/Extension/NotificationName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ import Foundation
extension Notification.Name {
static let selectDateDidChange = Notification.Name("selectDateDidChange")
static let selectDateisChanging = Notification.Name("selectDateisChanging")
static let moveSearchFlowNextStep = Notification.Name("moveSearchFlowNextStep")
}
17 changes: 17 additions & 0 deletions iOS/Arirbnb/Arirbnb/Extension/UIView+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// UIView+Extension.swift
// Arirbnb
//
// Created by 지북 on 2021/06/01.
//

import UIKit

extension UIView {
func configureFilteringViewLayout() {
self.heightAnchor.constraint(equalTo: superview?.heightAnchor ?? NSLayoutDimension(), multiplier: 0.725).isActive = true
}

@objc func configure() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class HeroImageCell: UICollectionViewCell, ReuseIdentifierable {
configure()
}

func configure() {
@objc override func configure() {
contentView.addSubview(heroImageView)

heroImageView.translatesAutoresizingMaskIntoConstraints = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,21 @@ class SearchFilteringViewController: UIViewController, ViewControllerIdentifiera
}

private lazy var filteringStackView = UIStackView()
private var filteringViews: [UIView] = []
private lazy var calendar = DumbaCalendar()
private lazy var sliderView = SliderView()
private lazy var filteringTableView = UITableView()
private lazy var flowView = SearchFlowView()

private var nowFilteringStep: Int = 0
private var destination: Destination?
private var filterItems: FilterItems?

override func viewDidLoad() {
super.viewDidLoad()
filteringViews = [calendar, sliderView]
configureStackView()
addSubViews()
configureCalendar()
configureTableView()
configureFilterItems()
addObservers()
Expand All @@ -56,9 +59,7 @@ class SearchFilteringViewController: UIViewController, ViewControllerIdentifiera
filteringStackView.distribution = .fill
configureStackViewLayout()
}
private func configureCalendar() {
calendar.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.725).isActive = true
}


private func configureTableView() {
filteringTableView.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -81,10 +82,12 @@ class SearchFilteringViewController: UIViewController, ViewControllerIdentifiera
private func addObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(setDateChange(_:)), name: .selectDateDidChange, object: calendar)
NotificationCenter.default.addObserver(self, selector: #selector(setDateIsChanging(_:)), name: .selectDateisChanging, object: calendar)
NotificationCenter.default.addObserver(self, selector: #selector(nextButtonDidTap(_:)), name: .moveSearchFlowNextStep, object: flowView)
}

private func addSubViews() {
filteringStackView.addArrangedSubview(calendar)
filteringStackView.addArrangedSubview(filteringViews[nowFilteringStep])
filteringViews[nowFilteringStep].configureFilteringViewLayout()
filteringStackView.addArrangedSubview(filteringTableView)
filteringStackView.addArrangedSubview(flowView)
}
Expand Down Expand Up @@ -118,6 +121,14 @@ extension SearchFilteringViewController {

flowView.doNotMeetTheConditions()
}

@objc func nextButtonDidTap(_ notification: Notification) {
filteringViews[nowFilteringStep].removeFromSuperview()
nowFilteringStep += 1
filteringStackView.insertArrangedSubview(filteringViews[nowFilteringStep], at: 0)
filteringViews[nowFilteringStep].configureFilteringViewLayout()
filteringViews[nowFilteringStep].configure()
}
}

//MARK: - Data Source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class SearchFlowView: UIView {
configure()
}

private func configure() {
@objc override func configure() {
skipButton.setTitle("건너뛰기", for: .normal)
skipButton.setTitleColor(.black, for: .normal)

Expand All @@ -39,6 +39,8 @@ class SearchFlowView: UIView {
addSubview(nextButton)

configureDefaultLayout()

nextButton.addTarget(self, action: #selector(nextButtonDidTap(_:)), for: .touchUpInside)
}

private func configureDefaultLayout() {
Expand Down Expand Up @@ -92,4 +94,8 @@ class SearchFlowView: UIView {
eraseButton.removeFromSuperview()
addSkipButton()
}

@objc func nextButtonDidTap(_ sendor: UIButton) {
NotificationCenter.default.post(name: .moveSearchFlowNextStep, object: self)
}
}
160 changes: 160 additions & 0 deletions iOS/Arirbnb/Arirbnb/SearchFilteringScene/View/Slider/DumbaSlider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//
// DumbaSlider.swift
// Arirbnb
//
// Created by 지북 on 2021/05/29.
//

import UIKit

class DumbaSlider: UIControl {
var minimumValue: CGFloat = 0
var maximumValue: CGFloat = 1
var lowerValue: CGFloat = 0.2
var upperValue: CGFloat = 0.8

var thumbImage = #imageLiteral(resourceName: "pause")



var trackTintColor = UIColor(white: 0.9, alpha: 1)
var trackHighlightTintColor = #colorLiteral(red: 0.9098039216, green: 0.2980392157, blue: 0.3764705882, alpha: 1)

private let lowerThumbImageView = UIImageView()
private let upperThumbImageView = UIImageView()
private var previousLocation = CGPoint()
private let trackLayer = RangeSliderTrackLayer()

override var frame: CGRect {
didSet {
updateLayerFrames()
}
}

override init(frame: CGRect) {
super.init(frame: frame)
configure()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}

@objc override func configure() {

trackLayer.rangeSlider = self
trackLayer.contentsScale = UIScreen.main.scale
layer.addSublayer(trackLayer)

lowerThumbImageView.image = thumbImage
addSubview(lowerThumbImageView)

upperThumbImageView.image = thumbImage
addSubview(upperThumbImageView)

}

private func updateLayerFrames() {
trackLayer.frame = bounds.insetBy(dx: 0.0, dy: bounds.height / 3)
trackLayer.setNeedsDisplay()
lowerThumbImageView.frame = CGRect(origin: thumbOriginForValue(lowerValue),
size: thumbImage.size)
upperThumbImageView.frame = CGRect(origin: thumbOriginForValue(upperValue),
size: thumbImage.size)
}

func positionForValue(_ value: CGFloat) -> CGFloat {
return bounds.width * value
}

private func thumbOriginForValue(_ value: CGFloat) -> CGPoint {
let x = positionForValue(value) - thumbImage.size.width / 2.0
return CGPoint(x: x, y: (bounds.height - thumbImage.size.height) / 2.0)
}
}

extension DumbaSlider {
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
// 1
previousLocation = touch.location(in: self)

// 2
if lowerThumbImageView.frame.contains(previousLocation) {
lowerThumbImageView.isHighlighted = true
} else if upperThumbImageView.frame.contains(previousLocation) {
upperThumbImageView.isHighlighted = true
}

// 3
return lowerThumbImageView.isHighlighted || upperThumbImageView.isHighlighted
}

override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let location = touch.location(in: self)

// 1
let deltaLocation = location.x - previousLocation.x
let deltaValue = (maximumValue - minimumValue) * deltaLocation / bounds.width

previousLocation = location

// 2
if lowerThumbImageView.isHighlighted {
lowerValue += deltaValue
lowerValue = boundValue(lowerValue, toLowerValue: minimumValue,
upperValue: upperValue)
} else if upperThumbImageView.isHighlighted {
upperValue += deltaValue
upperValue = boundValue(upperValue, toLowerValue: lowerValue,
upperValue: maximumValue)
}

// 3
CATransaction.begin()
CATransaction.setDisableActions(true)

updateLayerFrames()

CATransaction.commit()

return true
}

// 4
private func boundValue(_ value: CGFloat, toLowerValue lowerValue: CGFloat,
upperValue: CGFloat) -> CGFloat {
return min(max(value, lowerValue), upperValue)
}

override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
lowerThumbImageView.isHighlighted = false
upperThumbImageView.isHighlighted = false
}
}

class RangeSliderTrackLayer: CALayer {
weak var rangeSlider: DumbaSlider?

override func draw(in ctx: CGContext) {
guard let slider = rangeSlider else {
return
}

let path = UIBezierPath(roundedRect: bounds, cornerRadius: 10)
ctx.addPath(path.cgPath)

ctx.setFillColor(slider.trackTintColor.cgColor)
ctx.fillPath()

ctx.setFillColor(slider.trackHighlightTintColor.cgColor)
let lowerValuePosition = slider.positionForValue(slider.lowerValue)
let upperValuePosition = slider.positionForValue(slider.upperValue)
let rect = CGRect(x: lowerValuePosition, y: 0,
width: upperValuePosition - lowerValuePosition,
height: bounds.height)
ctx.fill(rect)
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// SliderView.swift
// Arirbnb
//
// Created by 지북 on 2021/06/01.
//

import UIKit

class SliderView: UIView {

private lazy var priceHeaderLabel = UILabel()
private lazy var slider = DumbaSlider()

override init(frame: CGRect) {
super.init(frame: frame)
configure()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}

@objc override func configure() {
slider.translatesAutoresizingMaskIntoConstraints = false
priceHeaderLabel.text = "가격 범위"
priceHeaderLabel.adjustsFontForContentSizeCategory = true
priceHeaderLabel.font = UIFont.preferredFont(forTextStyle: .headline)

addSubview(slider)
addSubview(priceHeaderLabel)


let margin: CGFloat = 20
let width = (superview?.bounds.width ?? 0) - 2 * margin
let height: CGFloat = 30

slider.frame = CGRect(x: 0, y: 0, width: width, height: height)
slider.center = superview?.center ?? CGPoint.zero
}
}
Loading

0 comments on commit 545e133

Please sign in to comment.