Skip to content

Commit

Permalink
[GWL-22] 운동 요약 화면 UI 구성 (#57)
Browse files Browse the repository at this point in the history
* feat: 운동 요약 화면을 갖는 ViewController, ViewModel 추가

* chore: 운동 종료버튼 접근성 힌트 추가

* chore: 운동참여 인원 CollectionView 추가

* feat: 운동 참여 인원 UI인 CollectionViewCell 추가

* feat: Diffable DataSource 적용

* feat: Custom Compositional Layout 구현

- Figma 디자인에 맞게 Layout을 수정했습니다.

* feat: CollectionView Cell Accessibility 추가

* feat: endWorkoutSubject 추가

endWorkoutButton이 눌렸을 때 endWorkoutSubject가 이벤트를 전달하도록 구현했습니다.
endWorkoutSubject는 Input이기에, 타입을 지우고 viewModel에게 파라미터로 넘겼습니다.

* chore: 하드코딩된 크기값과 제약조건값을 enum으로 관리
  • Loading branch information
WhiteHyun authored Nov 17, 2023
1 parent 142e48b commit 84e95aa
Show file tree
Hide file tree
Showing 4 changed files with 490 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//
// ParticipantsCollectionViewCell.swift
// RecordFeature
//
// Created by 홍승현 on 11/16/23.
// Copyright © 2023 kr.codesquad.boostcamp8. All rights reserved.
//

import DesignSystem
import UIKit

// MARK: - ParticipantsCollectionViewCell

final class ParticipantsCollectionViewCell: UICollectionViewCell {
// MARK: UI Components

private let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.backgroundColor = DesignSystemColor.primaryBackGround
imageView.layer.cornerRadius = Metrics.profileImageSize * 0.5
imageView.layer.cornerCurve = .continuous
imageView.clipsToBounds = true
return imageView
}()

private let nicknameLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .title3)
label.text = "S043_홍승현"
label.accessibilityHint = Strings.nicknameAccessibilityHint
return label
}()

private let distanceLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .title3, with: .traitBold)
label.text = "4.3km"
label.accessibilityHint = Strings.workoutDistanceAccessibilityHint
return label
}()

private let markingCircularContainerView: UIView = {
let shadowView = UIView()
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowOpacity = 0.25
shadowView.layer.shadowRadius = 2
shadowView.layer.shadowOffset = CGSize(width: 0, height: 2)
return shadowView
}()

private let markingCircularBackgroundView: UIView = {
let view = UIView()
view.backgroundColor = DesignSystemColor.main03
view.layer.cornerRadius = Metrics.markingSize * 0.5
return view
}()

private let textStackView: UIStackView = {
let stackView = UIStackView()
stackView.alignment = .leading
stackView.axis = .vertical
stackView.spacing = 2
return stackView
}()

private let imageIncludeStackView: UIStackView = {
let stackView = UIStackView()
stackView.spacing = 10
stackView.alignment = .center
return stackView
}()

private let wholeStackView: UIStackView = {
let stackView = UIStackView()
stackView.distribution = .equalSpacing
stackView.alignment = .top
return stackView
}()

private let containerView: UIView = {
let view = UIView()
view.layer.cornerRadius = 8
view.backgroundColor = DesignSystemColor.secondaryBackGround
return view
}()

// MARK: - Initializations

override init(frame: CGRect) {
super.init(frame: frame)
setupLayouts()
setupConstraints()
setupStyles()
}

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

private func setupLayouts() {
contentView.addSubview(containerView)
containerView.addSubview(wholeStackView)

wholeStackView.addArrangedSubview(imageIncludeStackView)
wholeStackView.addArrangedSubview(markingCircularContainerView)

markingCircularContainerView.addSubview(markingCircularBackgroundView)

imageIncludeStackView.addArrangedSubview(profileImageView)
imageIncludeStackView.addArrangedSubview(textStackView)

textStackView.addArrangedSubview(nicknameLabel)
textStackView.addArrangedSubview(distanceLabel)
}

private func setupConstraints() {
containerView.translatesAutoresizingMaskIntoConstraints = false
wholeStackView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.translatesAutoresizingMaskIntoConstraints = false
markingCircularContainerView.translatesAutoresizingMaskIntoConstraints = false
markingCircularBackgroundView.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate(
[
containerView.topAnchor.constraint(equalTo: contentView.topAnchor),
containerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
containerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),

wholeStackView.topAnchor.constraint(
equalTo: containerView.topAnchor,
constant: Metrics.wholeStackViewEdge
),
wholeStackView.bottomAnchor.constraint(
equalTo: containerView.bottomAnchor,
constant: -Metrics.wholeStackViewEdge
),
wholeStackView.leadingAnchor.constraint(
equalTo: containerView.leadingAnchor,
constant: Metrics.wholeStackViewEdge
),
wholeStackView.trailingAnchor.constraint(
equalTo: containerView.trailingAnchor,
constant: -Metrics.wholeStackViewEdge
),

profileImageView.widthAnchor.constraint(equalToConstant: Metrics.profileImageSize),
profileImageView.heightAnchor.constraint(equalToConstant: Metrics.profileImageSize),

markingCircularContainerView.widthAnchor.constraint(equalToConstant: Metrics.markingSize),
markingCircularContainerView.heightAnchor.constraint(equalToConstant: Metrics.markingSize),

markingCircularBackgroundView.topAnchor.constraint(equalTo: markingCircularContainerView.topAnchor),
markingCircularBackgroundView.bottomAnchor.constraint(equalTo: markingCircularContainerView.bottomAnchor),
markingCircularBackgroundView.leadingAnchor.constraint(equalTo: markingCircularContainerView.leadingAnchor),
markingCircularBackgroundView.trailingAnchor.constraint(equalTo: markingCircularContainerView.trailingAnchor),
]
)
}

private func setupStyles() {
contentView.layer.shadowColor = UIColor.black.cgColor
contentView.layer.shadowOpacity = 0.25
contentView.layer.shadowRadius = 2
contentView.layer.shadowOffset = CGSize(width: 0, height: 2)
contentView.backgroundColor = .clear
}

// MARK: Internal

func configure(with imageName: String) {
profileImageView.image = UIImage(systemName: imageName)
}
}

// MARK: ParticipantsCollectionViewCell.Metrics

private extension ParticipantsCollectionViewCell {
enum Metrics {
static let profileImageSize: CGFloat = 64
static let wholeStackViewEdge: CGFloat = 10
static let markingSize: CGFloat = 12
}

enum Strings {
static let nicknameAccessibilityHint = "닉네임"
static let workoutDistanceAccessibilityHint = "운동한 거리"
}
}
Loading

0 comments on commit 84e95aa

Please sign in to comment.