Skip to content

Commit

Permalink
feat: 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
MaraMincho committed Nov 17, 2023
1 parent 84e95aa commit 8f26a18
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 3 deletions.
5 changes: 2 additions & 3 deletions iOS/Projects/App/Sources/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import RecordFeature
import UIKit

final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
Expand All @@ -15,9 +16,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
guard let windowScene = scene as? UIWindowScene else { return }
let navigationController = UINavigationController()
window = UIWindow(windowScene: windowScene)
window?.rootViewController = navigationController
let coordinator = AppCoordinator(navigationController: navigationController)
coordinator.start()
window?.rootViewController = ExerciseEnvironmentSetupViewController()
window?.makeKeyAndVisible()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// ExerciseCardCell.swift
// RecordFeature
//
// Created by MaraMincho on 11/16/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import DesignSystem
import UIKit

// MARK: - ExerciseCardCell

class ExerciseCardCell: UICollectionViewCell {
static let identifier = "ExerciseCardCell"

override init(frame: CGRect) {
super.init(frame: frame)
shadowDecorate()
backgroundColor = .white
setupConstraints()
}

override var isSelected: Bool {
didSet {
if isSelected {
makeSelectUI()
} else {
makeDeslectUI()
}
}
}

private let exerciseIconDescriptionLagel: UILabel = {
let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .title3)
label.textAlignment = .center
label.text = "달리기에용"
label.contentMode = .scaleAspectFit

label.translatesAutoresizingMaskIntoConstraints = false
return label
}()

private let exerciseIcon: UIImageView = {
let config = UIImage.SymbolConfiguration(font: .systemFont(ofSize: 120))
let icon = UIImage(systemName: "figure.run", withConfiguration: config)
let imageView = UIImageView(image: icon)
imageView.contentMode = .scaleAspectFit
imageView.tintColor = DesignSystemColor.primaryText

imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()

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

private extension ExerciseCardCell {
func setupConstraints() {
contentView.addSubview(exerciseIconDescriptionLagel)
exerciseIconDescriptionLagel.bottomAnchor
.constraint(equalTo: contentView.bottomAnchor, constant: -12).isActive = true
exerciseIconDescriptionLagel.leadingAnchor
.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
exerciseIconDescriptionLagel.trailingAnchor
.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true

contentView.addSubview(exerciseIcon)
exerciseIcon.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true
exerciseIcon.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true
exerciseIcon.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5).isActive = true
exerciseIcon.bottomAnchor.constraint(equalTo: exerciseIconDescriptionLagel.topAnchor, constant: -15).isActive = true
}

func shadowDecorate() {
let radius: CGFloat = 10
contentView.layer.cornerRadius = radius
contentView.layer.borderWidth = 1
contentView.layer.borderColor = UIColor.clear.cgColor
contentView.layer.masksToBounds = true

layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 1.0)
layer.shadowRadius = 2.0
layer.shadowOpacity = 0.5
layer.masksToBounds = false
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
layer.cornerRadius = radius
}

func makeSelectUI() {
exerciseIcon.tintColor = DesignSystemColor.main03
exerciseIcon.makeShadow()
exerciseIconDescriptionLagel.textColor = DesignSystemColor.main03
exerciseIconDescriptionLagel.font = .preferredFont(forTextStyle: .title3, with: .traitBold)
}

func makeDeslectUI() {
exerciseIcon.tintColor = DesignSystemColor.primaryText
exerciseIcon.disableShadow()
exerciseIconDescriptionLagel.textColor = DesignSystemColor.primaryText
exerciseIconDescriptionLagel.font = .preferredFont(forTextStyle: .title3)
}
}

private extension UIImageView {
func makeShadow() {
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: -2, height: 2)
layer.shadowRadius = 2.0
layer.shadowOpacity = 0.3
layer.masksToBounds = false
}

func disableShadow() {
layer.shadowOpacity = 0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// ExerciseEnvironmentSetupViewController.swift
// RecordFeature
//
// Created by MaraMincho on 11/15/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import DesignSystem
import UIKit

// MARK: - ExerciseEnvironmentSetupViewController

public final class ExerciseEnvironmentSetupViewController: UIViewController {
public init() {
super.init(nibName: nil, bundle: nil)
}

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

override public func viewDidLoad() {
super.viewDidLoad()
setup()
}

override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

insertTempSource()
}

lazy var contentNAV: UINavigationController = {
let nav = UINavigationController(rootViewController: exerciseSelectView)

return nav
}()

private let exerciseSelectView = ExerciseSelectViewController()

private let pageControl: GWPageControl = {
let pageControl = GWPageControl(count: Const.countOfPage)

pageControl.translatesAutoresizingMaskIntoConstraints = false
return pageControl
}()

var dataSource: UICollectionViewDiffableDataSource<Int, UUID>!
var exerciseCardCollectionView: UICollectionView!
}

private extension ExerciseEnvironmentSetupViewController {
func setup() {
view.backgroundColor = .systemBackground
setupConstraints()
exerciseCardCollectionView = exerciseSelectView.exerciseCardCollectionView

configureDataSource()
}

func configureDataSource() {
dataSource = .init(collectionView: exerciseCardCollectionView, cellProvider: { collectionView, indexPath, _ in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ExerciseCardCell.identifier, for: indexPath)
return cell
})
}

func insertTempSource() {
var snapshot = dataSource.snapshot()
snapshot.deleteAllItems()
snapshot.appendSections([0])
snapshot.appendItems([.init(), .init(), .init(), .init(), .init()])

dataSource.apply(snapshot)
}

func setupConstraints() {
let safeArea = view.safeAreaLayoutGuide

view.addSubview(pageControl)
pageControl.topAnchor.constraint(equalTo: safeArea.topAnchor, constant: 10).isActive = true
pageControl.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: 23).isActive = true
pageControl.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor, constant: -23).isActive = true
pageControl.heightAnchor.constraint(equalToConstant: 30).isActive = true

view.addSubview(contentNAV.view)
contentNAV.view.translatesAutoresizingMaskIntoConstraints = false
contentNAV.view.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor).isActive = true
contentNAV.view.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor).isActive = true
contentNAV.view.topAnchor.constraint(equalTo: pageControl.bottomAnchor).isActive = true
contentNAV.view.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true
}

enum Const {
static let countOfPage = 2
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//
// ExerciseSelectViewController.swift
// RecordFeature
//
// Created by MaraMincho on 11/16/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import DesignSystem
import UIKit

// MARK: - ExerciseSelectViewController

final class ExerciseSelectViewController: UIViewController {
override init(nibName _: String?, bundle _: Bundle?) {
super.init(nibName: nil, bundle: nil)
}

override func viewDidLoad() {
super.viewDidLoad()
setupConstraints()
navigationController?.setNavigationBarHidden(true, animated: false)
}

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

private let exerciseSelectDescriptionLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .title1, with: .traitBold)
label.textAlignment = .left
label.text = "1. 운동을 선택하세요"

label.translatesAutoresizingMaskIntoConstraints = false
return label
}()

lazy var exerciseCardCollectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: makeCollectionViewLayout())
collectionView.register(ExerciseCardCell.self, forCellWithReuseIdentifier: ExerciseCardCell.identifier)

collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()

private let nextButton: UIButton = {
let button = UIButton()
button.configurationUpdateHandler = UIButton.Configuration.main(label: "다음")

button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
}

private extension ExerciseSelectViewController {
func makeCollectionViewLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1))

let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = .init(
top: Const.CellInset,
leading: Const.CellInset,
bottom: Const.CellInset,
trailing: Const.CellInset
)

let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalWidth(0.55))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

let section = NSCollectionLayoutSection(group: group)

return UICollectionViewCompositionalLayout(section: section)
}

func setupConstraints() {
let safeArea = view.safeAreaLayoutGuide

view.addSubview(exerciseSelectDescriptionLabel)
exerciseSelectDescriptionLabel.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true
exerciseSelectDescriptionLabel.leadingAnchor
.constraint(equalTo: safeArea.leadingAnchor, constant: ConstraintsGuideLine.value).isActive = true
exerciseSelectDescriptionLabel.trailingAnchor
.constraint(equalTo: safeArea.trailingAnchor, constant: -ConstraintsGuideLine.value).isActive = true

view.addSubview(exerciseCardCollectionView)
exerciseCardCollectionView.topAnchor
.constraint(equalTo: exerciseSelectDescriptionLabel.bottomAnchor, constant: 12).isActive = true
exerciseCardCollectionView.leadingAnchor
.constraint(equalTo: safeArea.leadingAnchor, constant: ConstraintsGuideLine.value).isActive = true
exerciseCardCollectionView.trailingAnchor
.constraint(equalTo: safeArea.trailingAnchor, constant: -ConstraintsGuideLine.value).isActive = true
exerciseCardCollectionView.bottomAnchor
.constraint(equalTo: view.bottomAnchor, constant: -15).isActive = true

view.addSubview(nextButton)
nextButton.leadingAnchor
.constraint(equalTo: safeArea.leadingAnchor, constant: ConstraintsGuideLine.value).isActive = true
nextButton.trailingAnchor
.constraint(equalTo: safeArea.trailingAnchor, constant: -ConstraintsGuideLine.value).isActive = true
nextButton.bottomAnchor
.constraint(equalTo: safeArea.bottomAnchor, constant: -28).isActive = true
}

enum Const {
static let CellInset: CGFloat = 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// ConstraintsGuideLine.swift
// DesignSystem
//
// Created by MaraMincho on 11/18/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import Foundation

public enum ConstraintsGuideLine {
public static let value: CGFloat = 23
}

0 comments on commit 8f26a18

Please sign in to comment.