diff --git a/Soyeon.xcodeproj/project.pbxproj b/Soyeon.xcodeproj/project.pbxproj index dd91f64..434faab 100644 --- a/Soyeon.xcodeproj/project.pbxproj +++ b/Soyeon.xcodeproj/project.pbxproj @@ -157,6 +157,8 @@ 1D7C3243268767E100D7F2C9 /* AppAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 1D7C3242268767E100D7F2C9 /* AppAuth */; }; 1D7C3245268767E100D7F2C9 /* AppAuthCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1D7C3244268767E100D7F2C9 /* AppAuthCore */; }; 1D7C32582687680100D7F2C9 /* AuthInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7C324F2687680100D7F2C9 /* AuthInfo.swift */; }; + 1D910ED526CA580200CB1EF5 /* RatingStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D910ED426CA580200CB1EF5 /* RatingStackView.swift */; }; + 1D910EDB26CA58A600CB1EF5 /* RatingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D910EDA26CA58A600CB1EF5 /* RatingView.swift */; }; 1DA32034262C757900ED564A /* LoadSignupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA32032262C757900ED564A /* LoadSignupView.swift */; }; 1DA32046262C75D900ED564A /* LoadSignupViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA32045262C75D900ED564A /* LoadSignupViewData.swift */; }; 1DBA13C425D440E400979BB2 /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = 1DBA13C325D440E400979BB2 /* Moya */; }; @@ -368,6 +370,8 @@ 1D5B63C625B4824F00A5321C /* StartSplashViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartSplashViewController.swift; sourceTree = ""; }; 1D64300425F4CBCE00A84D45 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; 1D7C324F2687680100D7F2C9 /* AuthInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthInfo.swift; sourceTree = ""; }; + 1D910ED426CA580200CB1EF5 /* RatingStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingStackView.swift; sourceTree = ""; }; + 1D910EDA26CA58A600CB1EF5 /* RatingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingView.swift; sourceTree = ""; }; 1DA32032262C757900ED564A /* LoadSignupView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadSignupView.swift; sourceTree = ""; }; 1DA32045262C75D900ED564A /* LoadSignupViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadSignupViewData.swift; sourceTree = ""; }; 1DC9DF4525AAEE7600822E99 /* PageViewType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PageViewType.swift; sourceTree = ""; }; @@ -1204,6 +1208,15 @@ path = AppAuth; sourceTree = ""; }; + 1D910ED126CA57CC00CB1EF5 /* RatingView */ = { + isa = PBXGroup; + children = ( + 1D910ED426CA580200CB1EF5 /* RatingStackView.swift */, + 1D910EDA26CA58A600CB1EF5 /* RatingView.swift */, + ); + path = RatingView; + sourceTree = ""; + }; 1DBA14DD25D46BE000979BB2 /* Signup */ = { isa = PBXGroup; children = ( @@ -1341,6 +1354,7 @@ D80D664A25BDBA1C002F47B9 /* Common */ = { isa = PBXGroup; children = ( + 1D910ED126CA57CC00CB1EF5 /* RatingView */, 008FB5B926885CBA00F4EF54 /* Manager */, 1DD0CCB6261A11AC003E6347 /* UserDefault */, 0A83E4232602549D001823C0 /* SoyeonToast */, @@ -1786,6 +1800,7 @@ 1D19088425A9F77E008210D1 /* AgreementInteractor.swift in Sources */, 0A4E515D25EAB4E400616C07 /* WriteProfileDefualtButton.swift in Sources */, 009B02AF25B47E9E00753847 /* LoginViewController.swift in Sources */, + 1D910EDB26CA58A600CB1EF5 /* RatingView.swift in Sources */, D8354D7D25B4348E00C9C531 /* NewAccountRouter.swift in Sources */, 0A4E515F25EAB4E400616C07 /* WriteProfileAlertAction.swift in Sources */, 0AC21E0F2613FDE400AD0635 /* AdditionalViewController.swift in Sources */, @@ -1885,6 +1900,7 @@ 0A9C2A552699D6340042692D /* KKOIDAuth.swift in Sources */, 0A4E515825EAB4E400616C07 /* JobAlertItem.swift in Sources */, 0AC21E162613FDE400AD0635 /* AdditionalRouter.swift in Sources */, + 1D910ED526CA580200CB1EF5 /* RatingStackView.swift in Sources */, D8354D7125B4347000C9C531 /* NewAccountConfigurator.swift in Sources */, 008FB5B426871F5200F4EF54 /* ImagePickerManager.swift in Sources */, 1D19087525A9F77E008210D1 /* DetailContents.swift in Sources */, @@ -1892,8 +1908,8 @@ 00CF092E25E25CA70077700A /* ProviderManager.swift in Sources */, 000CEB2D25B47FF400F64A28 /* UIView+.swift in Sources */, 1D5B63C725B4824F00A5321C /* StartSplashViewController.swift in Sources */, - 1D1908C925AA1645008210D1 /* PagingView.swift in Sources */, - 00E295E7266AB4DD00DB69CE /* UIImage+.swift in Sources */, + 1D1908C925AA1645008210D1 /* PagingView.swift in Sources */, + 00E295E7266AB4DD00DB69CE /* UIImage+.swift in Sources */, 0A9C2A63269A0C3E0042692D /* SYDefault.swift in Sources */, D8795C42258E6A2100DF4D64 /* SceneDelegate.swift in Sources */, 1DD0CCBC261A11F1003E6347 /* SoyeonUserDefault.swift in Sources */, diff --git a/Soyeon/Common/RatingView/RatingStackView.swift b/Soyeon/Common/RatingView/RatingStackView.swift new file mode 100644 index 0000000..1b21f12 --- /dev/null +++ b/Soyeon/Common/RatingView/RatingStackView.swift @@ -0,0 +1,153 @@ +// +// RatingStackView.swift +// Soyeon +// +// Created by 박은비 on 2021/08/16. +// Copyright © 2021 ludus. All rights reserved. +// + +import UIKit + +protocol RatingStackDelegate: AnyObject { + func didChangeIndex(_ index: Int) +} + +class RatingStackView: UIStackView { + + private var count: Int = 0 + private var imageSubViews: [UIImageView] = [] + private var subViewArea: CGFloat = 0.0 + + private var initalPointX: CGFloat = 0.0 // Gesture Property + + private var index: Int = -1 { + willSet { + delegate?.didChangeIndex(newValue) + setHighlight(until: newValue) + } + } + + weak var delegate: RatingStackDelegate? + + override init(frame: CGRect) { + super.init(frame: .zero) + + translatesAutoresizingMaskIntoConstraints = false + isUserInteractionEnabled = true + axis = .horizontal + + configureTapGesture() + configurePanGesture() + } + + required init(coder: NSCoder) { + super.init(coder: coder) + } + + convenience init(arrangedImageSubviews imageViews: [UIImageView]) { + self.init(frame: .zero) + + for view in imageViews { + self.addArrangedSubview(view) + } + + self.imageSubViews = imageViews + self.count = imageViews.count + + } + + override func draw(_ rect: CGRect) { + super.draw(rect) + + calcuratingArea() + } + + override func insertArrangedSubview(_ view: UIView, at stackIndex: Int) { } + override func removeArrangedSubview(_ view: UIView) { } + + override func addArrangedSubview(_ view: UIView) { + if imageSubViews.count == 0 { + super.addArrangedSubview(view) + } + } + + private func calcuratingArea() { + guard let firstView = arrangedSubviews.first else { return } + subViewArea = firstView.bounds.width + spacing + } + + private func numberHorizontal(of pointX: CGFloat) -> Int { + guard 0 < pointX else { return -1 } + let number = Int((pointX + spacing / 2.0) / subViewArea) + + guard number < arrangedSubviews.count else { return -1 } + + return number + } + + func changeIndex(to index: Int) { + guard self.index != index, 0 <= index else { + return + } + + self.index = min(index, count-1) + } + + private func setHighlight(until i: Int) { + imageSubViews[0...i].forEach { $0.isHighlighted = true } + imageSubViews[i+1.. [UIImageView] { + let imageName = attributes.imageName + let highlightColor = attributes.highlightColor + let count = attributes.count + + let imageViews: [UIImageView] = (0.. UIImage? { + let image = withRenderingMode(.alwaysTemplate) + return image.withTintColor(color) + } +} diff --git a/Soyeon/Intro/Base.lproj/Intro.storyboard b/Soyeon/Intro/Base.lproj/Intro.storyboard index 9f7518a..f17439b 100644 --- a/Soyeon/Intro/Base.lproj/Intro.storyboard +++ b/Soyeon/Intro/Base.lproj/Intro.storyboard @@ -68,7 +68,7 @@ - + diff --git a/Soyeon/Intro/StartSplash/PagingView.swift b/Soyeon/Intro/StartSplash/PagingView.swift index 8f4e235..f4af5f8 100644 --- a/Soyeon/Intro/StartSplash/PagingView.swift +++ b/Soyeon/Intro/StartSplash/PagingView.swift @@ -5,8 +5,7 @@ // Created by 박은비 on 2021/01/10. // Copyright © 2021 ludus. All rights reserved. // - -import Foundation + import UIKit final class PagingView: XibView { @@ -16,17 +15,11 @@ final class PagingView: XibView { private var items: [UIView] = [] { willSet { - DispatchQueue.main.async { [weak self] in - self?.setStackView(newValue) - self?.setPageConrol(newValue.count) - } + setStackView(newValue) + setPageConrol(newValue.count) } } - func setItems(_ items: [UIView]) { - self.items = items - } - private func setStackView(_ views: [UIView] ) { stackView.subviews.forEach { $0.removeFromSuperview() } @@ -46,6 +39,10 @@ final class PagingView: XibView { pageControl.currentPage = index } + func setItems(_ items: [UIView]) { + self.items = items + } + } extension PagingView: UIScrollViewDelegate { diff --git a/Soyeon/Intro/StartSplash/PagingView.xib b/Soyeon/Intro/StartSplash/PagingView.xib index 787074f..a293a96 100644 --- a/Soyeon/Intro/StartSplash/PagingView.xib +++ b/Soyeon/Intro/StartSplash/PagingView.xib @@ -9,9 +9,9 @@ - - - + + + diff --git a/Soyeon/Intro/StartSplash/XibView.swift b/Soyeon/Intro/StartSplash/XibView.swift index 7a6faaa..724a08e 100644 --- a/Soyeon/Intro/StartSplash/XibView.swift +++ b/Soyeon/Intro/StartSplash/XibView.swift @@ -5,8 +5,7 @@ // Created by 박은비 on 2021/01/17. // Copyright © 2021 ludus. All rights reserved. // - -import Foundation + import UIKit class XibView: UIView { @@ -21,19 +20,24 @@ class XibView: UIView { loadView() } - private func loadView() { - let name = String(describing: type(of: self)) + final private func loadView() { + let name = classname if let loadedNib = Bundle.main.loadNibNamed(name, owner: self, options: nil)?.first as? UIView { - self.addSubview(loadedNib) + addSubview(loadedNib) setFrame(loadedNib) } } - private func setFrame(_ view: UIView) { - self.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true - self.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true - self.topAnchor.constraint(equalTo: view.topAnchor).isActive = true - self.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + internal func setFrame(_ view: UIView) { + + let constraints = [ + leftAnchor.constraint(equalTo: view.leftAnchor), + rightAnchor.constraint(equalTo: view.rightAnchor), + topAnchor.constraint(equalTo: view.topAnchor), + bottomAnchor.constraint(equalTo: view.bottomAnchor) + ] + + NSLayoutConstraint.activate(constraints) } diff --git a/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/Contents.json b/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/Contents.json new file mode 100644 index 0000000..4b4e1f1 --- /dev/null +++ b/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "btn_star_rate@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "btn_star_rate@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/btn_star_rate@2x.png b/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/btn_star_rate@2x.png new file mode 100644 index 0000000..da426e0 Binary files /dev/null and b/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/btn_star_rate@2x.png differ diff --git a/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/btn_star_rate@3x.png b/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/btn_star_rate@3x.png new file mode 100644 index 0000000..ece9b8e Binary files /dev/null and b/Soyeon/Resources/Assets.xcassets/Button/btn_star_rate.imageset/btn_star_rate@3x.png differ