Skip to content

Commit

Permalink
Merge pull request #456 from sopt-makers/feat/#455-new-home-announcem…
Browse files Browse the repository at this point in the history
…ents-section-ui

[Feat] #455 - 신규 홈뷰 - 활동/비활동 홍보 섹션 UI 구현
  • Loading branch information
dlwogus0128 authored Dec 8, 2024
2 parents f57f598 + 2c02819 commit d42fbbb
Show file tree
Hide file tree
Showing 7 changed files with 380 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
//
// AnnouncementCardCVC.swift
// HomeFeature
//
// Created by Jae Hyun Lee on 11/28/24.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import UIKit

import Core
import DSKit

final class AnnouncementCardCVC: UICollectionViewCell {

// MARK: - UI Components

private let categoryTagView = HomeCategoryTagView()

private let dividerImageView = UIImageView().then {
$0.image = DSKitAsset.Assets.icVerticalDivider.image
$0.contentMode = .scaleAspectFit
}

private let categoryDetailLabel = UILabel().then {
$0.textColor = DSKitAsset.Colors.white.color
$0.font = DSKitFontFamily.Suit.medium.font(size: 12)
}

private let categoryStackView = UIStackView().then {
$0.axis = .horizontal
$0.alignment = .leading
$0.spacing = 10
}

private let writerProfileImageView = CustomProfileImageView()

private let writerNameLabel = UILabel().then {
$0.textColor = DSKitAsset.Colors.white.color
$0.font = DSKitFontFamily.Suit.regular.font(size: 13)
}

private let writerInfoStackView = UIStackView().then {
$0.axis = .horizontal
$0.spacing = 4
}

private let titleLabel = UILabel().then {
$0.textColor = DSKitAsset.Colors.white.color
$0.font = DSKitFontFamily.Suit.bold.font(size: 16)
$0.lineBreakMode = .byTruncatingTail
}

private let contentLabel = UILabel().then {
$0.textColor = DSKitAsset.Colors.gray300.color
$0.font = DSKitFontFamily.Suit.medium.font(size: 14)
$0.lineBreakMode = .byTruncatingTail
$0.textAlignment = .left
}

private let coverImageView = UIImageView().then {
$0.contentMode = .scaleToFill
$0.layer.cornerRadius = 8
$0.clipsToBounds = true
}

private let contentStackView = UIStackView().then {
$0.axis = .vertical
$0.alignment = .leading
$0.spacing = 12
}

// MARK: - Initialization

override init(frame: CGRect) {
super.init(frame: frame)
setStackView()
setUI()
setLayout()
}

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

// MARK: - UI & Layout

extension AnnouncementCardCVC {
private func setUI() {
self.backgroundColor = DSKitAsset.Colors.gray900.color
self.layer.cornerRadius = 12
}

private func setLayout() {
self.addSubviews(contentStackView)

writerProfileImageView.snp.makeConstraints { make in
make.size.equalTo(20)
}

coverImageView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.height.equalTo(160)
}

contentLabel.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
}

contentStackView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview().inset(16)
make.top.equalToSuperview().inset(14)
}
}

private func setStackView() {
categoryStackView.addArrangedSubviews(
categoryTagView,
dividerImageView,
categoryDetailLabel
)

writerInfoStackView.addArrangedSubviews(
writerProfileImageView,
writerNameLabel
)

contentStackView.addArrangedSubviews(
categoryStackView,
writerInfoStackView,
titleLabel,
contentLabel,
coverImageView
)
}
}

// MARK: - Methods

extension AnnouncementCardCVC {
func configureCell(model: AnnouncementInfo) {
self.categoryTagView.setData(with: model.categoryName, isHotTag: false)
self.categoryDetailLabel.text = model.categoryDetailName
self.writerProfileImageView.setImage(with: model.profileImage)
self.writerNameLabel.text = model.name
self.titleLabel.text = model.title
self.contentLabel.text = model.content

let hasCoverImage = (model.images != nil)
updateContentLayout(hasCoverImage: hasCoverImage)
if hasCoverImage, let cover = model.images {
self.coverImageView.setImage(with: cover)
} else {
updateContentLabelAttributes()
}
}

/// 사진이 있을 경우: content 한 줄 제한, 없을 경우: 이미지뷰 없이 제한 없는 content
private func updateContentLayout(hasCoverImage: Bool) {
if hasCoverImage {
self.coverImageView.isHidden = false
self.contentLabel.numberOfLines = 1
} else {
self.coverImageView.isHidden = true
self.contentLabel.numberOfLines = 0
}
}

/// contentLabel이 여러 줄일 경우
private func updateContentLabelAttributes() {
self.contentLabel.setLineSpacing(lineSpacing: 4)
self.contentLabel.lineBreakStrategy = .hangulWordPriority
self.contentLabel.numberOfLines = 9
self.contentLabel.lineBreakMode = .byTruncatingTail
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// AnnouncementPageContolFooterView.swift
// HomeFeature
//
// Created by Jae Hyun Lee on 11/28/24.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import UIKit
import Combine

import Core
import DSKit

final class AnnouncementPageContolFooterView: UICollectionViewCell {

// MARK: - Properties

private let cancelBag = CancelBag()

// MARK: - UI Components

private let cardPageControl = UIPageControl().then {
$0.currentPage = 0
$0.isUserInteractionEnabled = false
$0.backgroundStyle = .minimal
$0.currentPageIndicatorTintColor = DSKitAsset.Colors.white.color
$0.pageIndicatorTintColor = DSKitAsset.Colors.gray300.color
$0.hidesForSinglePage = true
$0.transform = .init(scaleX: 0.7, y: 0.7)
}

// MARK: - Initialization

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

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

// MARK: - UI & Layout

extension AnnouncementPageContolFooterView {
private func setLayout() {
self.addSubview(cardPageControl)

cardPageControl.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.leading.equalToSuperview().offset(-20)
}
}
}

// MARK: - Methods

extension AnnouncementPageContolFooterView {
func bind(input: PassthroughSubject<Int, Never>, pageNumber: Int) {
cardPageControl.numberOfPages = pageNumber
input
.withUnretained(self)
.sink { owner, currentPage in
owner.cardPageControl.currentPage = currentPage
}.store(in: cancelBag)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,12 @@ extension CoffeeChatCardCVC {
private func makeCategoryTagView(categories: [String]) {
for category in categories {
let categoryTag = HomeSquareTagView()
.setTitle(with: category)
.setTitleColor(with: DSKitAsset.Colors.success.color)
.setBackgroundColor(with: DSKitAsset.Colors.success.color.withAlphaComponent(0.2))
// .setTitle(with: category)
// .setTitleColor(with: DSKitAsset.Colors.success.color)
// .setBackgroundColor(with: DSKitAsset.Colors.success.color.withAlphaComponent(0.2))
categoryTag.setData(title: category,
titleColor: DSKitAsset.Colors.success.color,
backgroundColor: DSKitAsset.Colors.success.color.withAlphaComponent(0.2))
self.categoryTagStackView.addArrangedSubviews(categoryTag)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import UIKit
import Combine

import Core

Expand All @@ -19,6 +20,7 @@ extension HomeForMemberVC {

static let productItemSpacing: Double = 15
static let appServiceItemSpacing: Double = 16
static let announcementWidth: Double = 300
}

func createLayout() -> UICollectionViewCompositionalLayout {
Expand All @@ -35,6 +37,8 @@ extension HomeForMemberVC {
return self.createAppServiceSection()
case .insight:
return self.createInsightSection()
case .announcement:
return self.createAnnouncementSection()
case .group:
return self.createGroupSection()
case .coffeeChat:
Expand Down Expand Up @@ -224,13 +228,60 @@ extension HomeForMemberVC {
section.boundarySupplementaryItems = [header]
section.contentInsets = NSDirectionalEdgeInsets(top: 16,
leading: Metric.collectionViewDefaultSideInset,
bottom: 0,
trailing: 0)
bottom: Metric.defaultLineSpacing,
trailing: Metric.collectionViewDefaultSideInset)
section.interGroupSpacing = 12
section.orthogonalScrollingBehavior = .groupPaging
return section
}

private func createAnnouncementSection() -> NSCollectionLayoutSection {
/// header: default
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(30))
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize,
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .top)

/// item: 홍보 카드
let announcementItemSize = NSCollectionLayoutSize(widthDimension: .absolute(Metric.announcementWidth),
heightDimension: .absolute(308))
let announctementItem = NSCollectionLayoutItem(layoutSize: announcementItemSize)

/// group: 홍보 카드
let announcementGroupSize = NSCollectionLayoutSize(widthDimension: .absolute(Metric.announcementWidth),
heightDimension: .absolute(308))
let announcementGroup = NSCollectionLayoutGroup.vertical(layoutSize: announcementGroupSize,
subitems: [announctementItem])

/// section 지정
let section = NSCollectionLayoutSection(group: announcementGroup)
section.boundarySupplementaryItems = [header]
section.contentInsets = NSDirectionalEdgeInsets(top: 16,
leading: Metric.collectionViewDefaultSideInset,
bottom: 0,
trailing: Metric.collectionViewDefaultSideInset)

/// footer: pageController 추가
let footerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(24))
let footer = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: footerSize,
elementKind: UICollectionView.elementKindSectionFooter,
alignment: .bottomLeading)

/// 포커스 중인 페이지 인덱스 계산
section.visibleItemsInvalidationHandler = { [weak self] items, offset, env in
let pageWidth = Metric.announcementWidth
let currentPage = Int(ceil(offset.x / (pageWidth + Metric.defaultGroupSpacing)))
self?.viewModel.currentCardPage.send(currentPage)
}

section.boundarySupplementaryItems = [header, footer]
section.orthogonalScrollingBehavior = .groupPaging
section.interGroupSpacing = 12
return section
}

private func createEmptySection() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(1),
heightDimension: .absolute(1))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,4 @@ extension HomeSquareTagView {
self.titleLabel.textColor = titleColor
self.backgroundColor = backgroundColor
}

@discardableResult
public func setTitle(with title: String) -> Self {
self.titleLabel.text = title
return self
}

@discardableResult
public func setTitleColor(with color: UIColor) -> Self {
self.titleLabel.textColor = color
return self
}

@discardableResult
public func setBackgroundColor(with color: UIColor) -> Self {
self.backgroundColor = color
return self
}
}

Loading

0 comments on commit d42fbbb

Please sign in to comment.