Skip to content

Commit

Permalink
[Design] - We-Are-Techl#17 온보딩 View & VC 작성
Browse files Browse the repository at this point in the history
  • Loading branch information
ILWAT committed Jan 18, 2023
1 parent 262e704 commit 24b5b47
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Techl-Neo/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }

let vc = ViewController() // 여길 바꿔서 첫 화면 이동
let vc = OnboardingVC() // 여길 바꿔서 첫 화면 이동
let window = UIWindow(windowScene: windowScene)
window.rootViewController = vc
self.window = window
Expand Down
1 change: 0 additions & 1 deletion Techl-Neo/Presentations/Base/BaseVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class BaseVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

self.view.backgroundColor = .systemBackground
configure()
setNavigationBar()

Expand Down
3 changes: 2 additions & 1 deletion Techl-Neo/Presentations/Base/BaseView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class BaseView: UIView {
/// - VC의 loadView() 메서드를 오버라이딩후 super 메서드를 호출하지 않고 view = 커스텀뷰()로 바꿔주어야 합니다.
override init(frame: CGRect) {
super.init(frame: frame)

backgroundColor = .systemBackground

setupUI()
setConstraints()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,58 @@ class OnboardingCollectionViewCell: UICollectionViewCell {

static let identifier = "OnboardingCollectionViewCell"

weak var thumbnailImageView: UIImageView!
weak var titleLabel: UILabel!
weak var descriptionLabel: UILabel!
let thumbnailImageView = UIImageView()
let titleLabel = UILabel().then{
$0.textAlignment = .center
$0.font = UIFont(name: "Apple SD Gothic Neo Bold", size: 28)
}
let descriptionLabel = UILabel().then{
$0.numberOfLines = 2
$0.textAlignment = .center
$0.font = UIFont(name: "Apple SD Gothic Neo SemiBold", size: 22)
}

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

setUI()
setConstraints()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func configure(_ message: OnboardingMessage) {
thumbnailImageView.image = UIImage(named: message.imageName)
titleLabel.text = message.title
descriptionLabel.text = message.description
}

func setUI(){
contentView.addSubview(titleLabel)
contentView.addSubview(descriptionLabel)
contentView.addSubview(thumbnailImageView)
}

func setConstraints(){
titleLabel.snp.makeConstraints { make in
make.top.greaterThanOrEqualTo(contentView.snp.top).offset(24)
make.trailing.equalTo(contentView.snp.trailing).offset(-24) // x좌표 기준으로 -24가 되어야 하기 때문에
make.leading.equalTo(contentView.snp.leading).offset(24)

}
descriptionLabel.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(3)
make.trailing.equalTo(titleLabel.snp.trailing)
make.leading.equalTo(titleLabel.snp.leading)
}

thumbnailImageView.snp.makeConstraints{ make in
make.trailing.equalTo(titleLabel.snp.trailing)
make.leading.equalTo(titleLabel.snp.leading)
make.top.equalTo(descriptionLabel.snp.bottom).offset(31)
make.height.equalTo(thumbnailImageView.snp.width).multipliedBy(1/1) //aspect ratio 1:1
}
}
}
128 changes: 128 additions & 0 deletions Techl-Neo/Presentations/Onboarding/OnboardingVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,148 @@

import UIKit

/// 베이스 뷰 컨트롤러
/// - loadView() 메서드를 오버라이드한 후 view를 커스텀 뷰로 교체해줄 수 있다.
class OnboardingVC: BaseVC {

//MARK: - Properties

let onboardingView = OnboardingView()


var isFinished: Bool = false

let messages: [OnboardingMessage] = OnboardingMessage.messages

var currentIndex: Int = 0 { // skipButton isHidden 설정 변수
didSet {
buttonDesignUI()
onboardingView.skipButton.isHidden = (currentIndex == messages.count - 1 ? true : false)
if currentIndex < messages.count - 1 {
isFinished = false
}
}
}
//MARK: - LifeCycle
override func loadView() {
view = onboardingView
}
override func viewDidLoad() {
super.viewDidLoad()
}

//MARK: - configure
/// Delegate, Register, AddTarget 등
override func configure() {
onboardingView.onboardingCollectionView.delegate = self
onboardingView.onboardingCollectionView.dataSource = self

onboardingView.onboardingCollectionView.register(OnboardingCollectionViewCell.self, forCellWithReuseIdentifier: OnboardingCollectionViewCell.identifier)
onboardingView.skipButton.addTarget(self, action: #selector(skipButtonTapped(_:)), for: .touchUpInside)
onboardingView.nextButton.addTarget(self, action: #selector(nextButtonTapped(_:)), for: .touchUpInside)
}

//MARK: - setNavigationBar

/// 네비게이션 바 설정
/// - 타이틀, 아이템 등 네비게이션과 관련된 설정을 합니다.
override func setNavigationBar() {
}

//MARK: - Helper

@objc func nextButtonTapped(_ sender: UIButton!){
let index = currentIndex == messages.count - 1 ? currentIndex : (currentIndex + 1) % 3
currentIndex = index

onboardingView.onboardingCollectionView.scrollToItem(at: [0, currentIndex], at: .right, animated: true)

onboardingView.pageControl.currentPage = currentIndex

if isFinished == true {

print("skip")
}

if onboardingView.nextButton.currentTitle == "완료" && currentIndex == messages.count - 1 {
// 완료일 때 화면 이동
isFinished = true
}

}

@objc func skipButtonTapped(_ sender: UIButton!){
print("skip")
}

func buttonDesignUI() {
onboardingView.nextButton.titleLabel?.font = UIFont(name: "Apple SD Gothic Neo SemiBold", size: 14)
onboardingView.nextButton.layer.cornerRadius = 8


if currentIndex < messages.count - 1 {
onboardingView.skipButton.isHidden = false
onboardingView.nextButton.setTitle("다음", for: .normal)
onboardingView.nextButton.setImage(UIImage(systemName: "chevron.right"), for: .normal)

} else { // 완료일 때 화면전환
onboardingView.skipButton.isHidden = true
onboardingView.nextButton.setTitle("완료", for: .normal)
onboardingView.nextButton.setImage(UIImage(), for: .normal)
onboardingView.nextButton.layer.borderWidth = 0
}
}

}

//MARK: - extenstion

extension OnboardingVC: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return messages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OnboardingCollectionViewCell.identifier, for: indexPath) as? OnboardingCollectionViewCell else { return UICollectionViewCell() }

let message = messages[indexPath.item]
cell.configure(message)

return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width: CGFloat = UIScreen.main.bounds.width
let height: CGFloat = collectionView.bounds.height
return CGSize(width: width, height: height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return .zero
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return .zero
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .zero
}
}

extension OnboardingVC: UIScrollViewDelegate {
//현재 페이지가 어디에 위치해 있는지 Indexing 하는 메소드
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let index = Int(scrollView.contentOffset.x/scrollView.bounds.width)
onboardingView.pageControl.currentPage = index
currentIndex = index

}
//carousel 적용 메소드
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let scrolledOffsetX = targetContentOffset.pointee.x + scrollView.contentInset.left
let cellWidth = UIScreen.main.bounds.width
let index = round(scrolledOffsetX / cellWidth)
targetContentOffset.pointee = CGPoint(x: index * cellWidth - scrollView.contentInset.left, y: scrollView.contentInset.top)
}
}

77 changes: 68 additions & 9 deletions Techl-Neo/Presentations/Onboarding/OnboardingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,101 @@ import UIKit
import SnapKit
import Then


class OnboardingView: BaseView {
// MARK: - Properties
let identifier = "OnboardingView"

let onboardingCollectionView: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()).then { //CollectionView
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal //CollectionView scroll 방향을 수평으로 설정합니다.
$0.decelerationRate = .fast //사용자가 손가락을 뗀 후 감속 비율을 결정하는 부동 소수점 값입니다. -> 빠르게 설정
$0.collectionViewLayout = layout
$0.backgroundColor = .clear //collectionView의 배경을 투명하게 만듭니다.
$0.showsHorizontalScrollIndicator = false //collectionView의 스크롤바가 보이지 않게 설정합니다.
}

var onboardingCollectionView: UICollectionView!
let pageControl: UIPageControl = UIPageControl().then { make in
let pageControl: UIPageControl = UIPageControl().then {
$0.currentPageIndicatorTintColor = UIColor.CustomColor.primaryColor
$0.tintColor = .darkGray
$0.isUserInteractionEnabled = false
$0.numberOfPages = OnboardingMessage.messages.count
$0.currentPage = 0
}

let skipButton: UIButton = UIButton().then {
$0.isHidden = false
$0.titleLabel?.font = UIFont(name: "Apple SD Gothic Neo SemiBold", size: 14)
$0.setTitle("건너뛰기", for: .normal)
$0.setTitleColor(.darkGray, for: .normal)
$0.backgroundColor = .clear
}

let nextButton: UIButton = UIButton().then {
$0.setTitle("다음", for: .normal)
$0.setImage(UIImage(systemName: "chevron.right"), for: .normal)
$0.semanticContentAttribute = .forceRightToLeft //이미지를 텍스트 오른쪽으로 변경
$0.titleLabel?.font = UIFont(name: "Apple SD Gothic Neo SemiBold", size: 14)
$0.layer.cornerRadius = 8
$0.setImage(UIImage(systemName: "chevron.right"), for: .normal)
$0.backgroundColor = .CustomColor.primaryColor
$0.tintColor = .white
}


override init(frame: CGRect) {
super.init(frame: frame)
var stackView = UIStackView().then{
$0.distribution = .fillProportionally
$0.spacing = 17
$0.axis = .horizontal
}

required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

// MARK: - setupUI
/// UI 설정
/// - addSubviews를 하거나 뷰의 배경색을 바꾸는 등 설정을 합니다.
override func setupUI() {

self.addSubview(onboardingCollectionView)
self.addSubview(pageControl)
stackView.insertArrangedSubview(skipButton, at: 0)
stackView.insertArrangedSubview(nextButton, at: 1)
self.addSubview(stackView)
backgroundColor = .CustomColor.backgroundColor
}


// MARK: - setConstraints
/// UI 제약조건 설정
/// - Anchor, Snapkit 등을 이용해 UI 컴포넌트의 위치, 크기 등 제약조건을 설정합니다.
override func setConstraints() {
pageControl.snp.makeConstraints{ make in
make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(24)
make.centerX.equalTo(safeAreaLayoutGuide.snp.centerX)
}

onboardingCollectionView.snp.makeConstraints { make in
make.trailing.leading.equalToSuperview()
make.trailing.leading.equalTo(safeAreaLayoutGuide)
make.top.equalTo(pageControl.snp.bottom).offset(10)
make.height.equalTo(safeAreaLayoutGuide.snp.height).multipliedBy(0.669643)
}

nextButton.snp.makeConstraints { make in
make.height.equalTo(stackView.snp.height)
}

skipButton.snp.makeConstraints{ make in
make.width.equalTo(stackView.snp.width).multipliedBy(0.25)
}

stackView.snp.makeConstraints { make in
make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(24)
make.trailing.equalTo(safeAreaLayoutGuide.snp.trailing).offset(-24)
make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-30) //바닥 보다 30 올라가야 하기 때문에 offset -30
make.height.equalTo(50)
}
}

//MARK: - Helper



}


0 comments on commit 24b5b47

Please sign in to comment.