-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 기능 구현 * chore: sceneDelegate수정 * chor: CardCell에 Rounded기능과 DropShadow 함수 이름 수정 * chor: SceneDelegate 수정 * chor: 피드백 반영 오타 및 함수명 변경 * chore: 다크모드 대응 * chor: 피드백 반영 * chor: 디렉토리 이름 변경
- Loading branch information
1 parent
84e95aa
commit e2b0285
Showing
5 changed files
with
328 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
iOS/Projects/Features/Record/Sources/WorkoutSelectScene/View/WorkoutCardCell.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// | ||
// WorkoutCardCell.swift | ||
// RecordFeature | ||
// | ||
// Created by MaraMincho on 11/16/23. | ||
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved. | ||
// | ||
|
||
import DesignSystem | ||
import UIKit | ||
|
||
// MARK: - WorkoutCardCell | ||
|
||
class WorkoutCardCell: UICollectionViewCell { | ||
static let identifier = "WorkoutCardCell" | ||
|
||
override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
makeShadowAndRounded() | ||
backgroundColor = DesignSystemColor.primaryBackGround | ||
setupConstraints() | ||
} | ||
|
||
override var isSelected: Bool { | ||
didSet { | ||
if isSelected { | ||
makeSelectUI() | ||
} else { | ||
makeDeslectUI() | ||
} | ||
} | ||
} | ||
|
||
private let workoutIconDescriptionLabel: 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 workoutIcon: 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 WorkoutCardCell { | ||
func setupConstraints() { | ||
contentView.addSubview(workoutIconDescriptionLabel) | ||
workoutIconDescriptionLabel.bottomAnchor | ||
.constraint(equalTo: contentView.bottomAnchor, constant: -12).isActive = true | ||
workoutIconDescriptionLabel.leadingAnchor | ||
.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true | ||
workoutIconDescriptionLabel.trailingAnchor | ||
.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true | ||
|
||
contentView.addSubview(workoutIcon) | ||
workoutIcon.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true | ||
workoutIcon.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true | ||
workoutIcon.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5).isActive = true | ||
workoutIcon.bottomAnchor.constraint(equalTo: workoutIconDescriptionLabel.topAnchor, constant: -15).isActive = true | ||
} | ||
|
||
func makeShadowAndRounded() { | ||
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() { | ||
workoutIcon.tintColor = DesignSystemColor.main03 | ||
workoutIcon.makeShadow() | ||
|
||
workoutIconDescriptionLabel.textColor = DesignSystemColor.main03 | ||
workoutIconDescriptionLabel.font = .preferredFont(forTextStyle: .title3, with: .traitBold) | ||
} | ||
|
||
func makeDeslectUI() { | ||
workoutIcon.tintColor = DesignSystemColor.primaryText | ||
workoutIcon.disableShadow() | ||
|
||
workoutIconDescriptionLabel.textColor = DesignSystemColor.primaryText | ||
workoutIconDescriptionLabel.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 | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
...atures/Record/Sources/WorkoutSelectScene/View/WorkoutEnvironmentSetupViewController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// | ||
// WorkoutEnvironmentSetupViewController.swift | ||
// RecordFeature | ||
// | ||
// Created by MaraMincho on 11/15/23. | ||
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved. | ||
// | ||
|
||
import DesignSystem | ||
import UIKit | ||
|
||
// MARK: - WorkoutEnvironmentSetupViewController | ||
|
||
public final class WorkoutEnvironmentSetupViewController: UIViewController { | ||
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: workoutSelectView) | ||
|
||
return nav | ||
}() | ||
|
||
private let workoutSelectView = WorkoutSelectViewController() | ||
|
||
private let pageControl: GWPageControl = { | ||
let pageControl = GWPageControl(count: Constant.countOfPage) | ||
|
||
pageControl.translatesAutoresizingMaskIntoConstraints = false | ||
return pageControl | ||
}() | ||
|
||
var dataSource: UICollectionViewDiffableDataSource<Int, UUID>! | ||
var workoutCardCollectionView: UICollectionView! | ||
} | ||
|
||
private extension WorkoutEnvironmentSetupViewController { | ||
func setup() { | ||
view.backgroundColor = .systemBackground | ||
setupViewHierarchyAndConstraints() | ||
workoutCardCollectionView = workoutSelectView.workoutCardCollectionView | ||
|
||
configureDataSource() | ||
} | ||
|
||
func configureDataSource() { | ||
dataSource = .init(collectionView: workoutCardCollectionView, cellProvider: { collectionView, indexPath, _ in | ||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WorkoutCardCell.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 setupViewHierarchyAndConstraints() { | ||
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 Constant { | ||
static let countOfPage = 2 | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
...rojects/Features/Record/Sources/WorkoutSelectScene/View/WorkoutSelectViewController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// | ||
// WorkoutSelectViewController.swift | ||
// RecordFeature | ||
// | ||
// Created by MaraMincho on 11/16/23. | ||
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved. | ||
// | ||
|
||
import DesignSystem | ||
import UIKit | ||
|
||
// MARK: - WorkoutSelectViewController | ||
|
||
final class WorkoutSelectViewController: UIViewController { | ||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
setupConstraints() | ||
navigationController?.setNavigationBarHidden(true, animated: false) | ||
} | ||
|
||
private let workoutSelectDescriptionLabel: UILabel = { | ||
let label = UILabel() | ||
label.font = .preferredFont(forTextStyle: .title1, with: .traitBold) | ||
label.textAlignment = .left | ||
label.text = "1. 운동을 선택하세요" | ||
|
||
label.translatesAutoresizingMaskIntoConstraints = false | ||
return label | ||
}() | ||
|
||
lazy var workoutCardCollectionView: UICollectionView = { | ||
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: makeCollectionViewLayout()) | ||
collectionView.register(WorkoutCardCell.self, forCellWithReuseIdentifier: WorkoutCardCell.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 WorkoutSelectViewController { | ||
func makeCollectionViewLayout() -> UICollectionViewLayout { | ||
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1)) | ||
|
||
let item = NSCollectionLayoutItem(layoutSize: itemSize) | ||
item.contentInsets = .init( | ||
top: Const.cellInsets, | ||
leading: Const.cellInsets, | ||
bottom: Const.cellInsets, | ||
trailing: Const.cellInsets | ||
) | ||
|
||
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(workoutSelectDescriptionLabel) | ||
workoutSelectDescriptionLabel.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true | ||
workoutSelectDescriptionLabel.leadingAnchor | ||
.constraint(equalTo: safeArea.leadingAnchor, constant: ConstraintsGuideLine.value).isActive = true | ||
workoutSelectDescriptionLabel.trailingAnchor | ||
.constraint(equalTo: safeArea.trailingAnchor, constant: -ConstraintsGuideLine.value).isActive = true | ||
|
||
view.addSubview(workoutCardCollectionView) | ||
workoutCardCollectionView.topAnchor | ||
.constraint(equalTo: workoutSelectDescriptionLabel.bottomAnchor, constant: 12).isActive = true | ||
workoutCardCollectionView.leadingAnchor | ||
.constraint(equalTo: safeArea.leadingAnchor, constant: ConstraintsGuideLine.value).isActive = true | ||
workoutCardCollectionView.trailingAnchor | ||
.constraint(equalTo: safeArea.trailingAnchor, constant: -ConstraintsGuideLine.value).isActive = true | ||
workoutCardCollectionView.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 cellInsets: CGFloat = 5 | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
iOS/Projects/Shared/DesignSystem/Sources/ConstraintsGuideLine.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |