Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#6] 영화,드라마 선택 화면 구현 #13

Merged
merged 6 commits into from
Jan 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion TodayVideo/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 5fd0e82f9fae1f129233777aee57aa7cc753fb9d

COCOAPODS: 1.16.2
COCOAPODS: 1.12.1
44 changes: 44 additions & 0 deletions TodayVideo/TodayVideo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
47B663CC8D8E3B9C6597D6A8 /* Pods_TodayVideo_TodayVideoUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFB8528AC96E0E4545364CA7 /* Pods_TodayVideo_TodayVideoUITests.framework */; };
642F696B881908AADE34D680 /* Pods_TodayVideoTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A000755573841D92675025D /* Pods_TodayVideoTests.framework */; };
CE0F3FF32D374BA40058CEAE /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F3FF22D374BA40058CEAE /* UIColor+Extensions.swift */; };
CE0F3FF62D37714B0058CEAE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F3FF52D37714B0058CEAE /* ContentView.swift */; };
CE0F3FF82D3771C80058CEAE /* ContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F3FF72D3771C80058CEAE /* ContentPresenter.swift */; };
CE0F3FFA2D3771D40058CEAE /* ContentRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F3FF92D3771D40058CEAE /* ContentRouter.swift */; };
CE0F3FFE2D38A2850058CEAE /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F3FFD2D38A2850058CEAE /* UIImage+Extension.swift */; };
CE0F40012D38A6590058CEAE /* FilterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F40002D38A6590058CEAE /* FilterButton.swift */; };
CE0F40032D38E0720058CEAE /* NextButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F40022D38E0720058CEAE /* NextButton.swift */; };
CE0F40052D39D2B80058CEAE /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0F40042D39D2B80058CEAE /* String+Extension.swift */; };
CE9EAC182D2239E100971DB4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9EAC172D2239E100971DB4 /* AppDelegate.swift */; };
CE9EAC1A2D2239E100971DB4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9EAC192D2239E100971DB4 /* SceneDelegate.swift */; };
CE9EAC1C2D2239E100971DB4 /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9EAC1B2D2239E100971DB4 /* SplashView.swift */; };
Expand Down Expand Up @@ -51,6 +58,13 @@
BDE0F86382A97508FF432E23 /* Pods-TodayVideo-TodayVideoUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TodayVideo-TodayVideoUITests.debug.xcconfig"; path = "Target Support Files/Pods-TodayVideo-TodayVideoUITests/Pods-TodayVideo-TodayVideoUITests.debug.xcconfig"; sourceTree = "<group>"; };
C7E44DA69C861B3423EEE105 /* Pods-TodayVideo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TodayVideo.debug.xcconfig"; path = "Target Support Files/Pods-TodayVideo/Pods-TodayVideo.debug.xcconfig"; sourceTree = "<group>"; };
CE0F3FF22D374BA40058CEAE /* UIColor+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extensions.swift"; sourceTree = "<group>"; };
CE0F3FF52D37714B0058CEAE /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
CE0F3FF72D3771C80058CEAE /* ContentPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentPresenter.swift; sourceTree = "<group>"; };
CE0F3FF92D3771D40058CEAE /* ContentRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentRouter.swift; sourceTree = "<group>"; };
CE0F3FFD2D38A2850058CEAE /* UIImage+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = "<group>"; };
CE0F40002D38A6590058CEAE /* FilterButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterButton.swift; sourceTree = "<group>"; };
CE0F40022D38E0720058CEAE /* NextButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextButton.swift; sourceTree = "<group>"; };
CE0F40042D39D2B80058CEAE /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
CE9EAC142D2239E100971DB4 /* TodayVideo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TodayVideo.app; sourceTree = BUILT_PRODUCTS_DIR; };
CE9EAC172D2239E100971DB4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
CE9EAC192D2239E100971DB4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -111,10 +125,31 @@
isa = PBXGroup;
children = (
CE0F3FF22D374BA40058CEAE /* UIColor+Extensions.swift */,
CE0F3FFD2D38A2850058CEAE /* UIImage+Extension.swift */,
CE0F40042D39D2B80058CEAE /* String+Extension.swift */,
);
path = Extension;
sourceTree = "<group>";
};
CE0F3FF42D3771220058CEAE /* ContentView */ = {
isa = PBXGroup;
children = (
CE0F3FF52D37714B0058CEAE /* ContentView.swift */,
CE0F3FF72D3771C80058CEAE /* ContentPresenter.swift */,
CE0F3FF92D3771D40058CEAE /* ContentRouter.swift */,
);
path = ContentView;
sourceTree = "<group>";
};
CE0F3FFF2D38A63F0058CEAE /* Common */ = {
isa = PBXGroup;
children = (
CE0F40002D38A6590058CEAE /* FilterButton.swift */,
CE0F40022D38E0720058CEAE /* NextButton.swift */,
);
path = Common;
sourceTree = "<group>";
};
CE9EAC0B2D2239E100971DB4 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -146,8 +181,10 @@
CE9EAC202D2239E200971DB4 /* Assets.xcassets */,
CE9EAC222D2239E200971DB4 /* LaunchScreen.storyboard */,
CE9EAC252D2239E200971DB4 /* Info.plist */,
CE0F3FFF2D38A63F0058CEAE /* Common */,
CE0F3FF12D374B0F0058CEAE /* Extension */,
CE9EAC472D223ACC00971DB4 /* SplashView */,
CE0F3FF42D3771220058CEAE /* ContentView */,
);
path = TodayVideo;
sourceTree = "<group>";
Expand Down Expand Up @@ -433,10 +470,17 @@
files = (
CE9EAC1C2D2239E100971DB4 /* SplashView.swift in Sources */,
CE0F3FF32D374BA40058CEAE /* UIColor+Extensions.swift in Sources */,
CE0F3FF62D37714B0058CEAE /* ContentView.swift in Sources */,
CE9EAC182D2239E100971DB4 /* AppDelegate.swift in Sources */,
CE0F3FF82D3771C80058CEAE /* ContentPresenter.swift in Sources */,
CE9EAC4B2D223B2D00971DB4 /* SplashRouter.swift in Sources */,
CE0F40032D38E0720058CEAE /* NextButton.swift in Sources */,
CE0F40012D38A6590058CEAE /* FilterButton.swift in Sources */,
CE9EAC492D223B2300971DB4 /* SplashPresenter.swift in Sources */,
CE0F3FFE2D38A2850058CEAE /* UIImage+Extension.swift in Sources */,
CE0F40052D39D2B80058CEAE /* String+Extension.swift in Sources */,
CE9EAC1A2D2239E100971DB4 /* SceneDelegate.swift in Sources */,
CE0F3FFA2D3771D40058CEAE /* ContentRouter.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
12 changes: 12 additions & 0 deletions TodayVideo/TodayVideo/Assets.xcassets/next.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Vector.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions TodayVideo/TodayVideo/Common/FilterButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// FilterButton.swift
// TodayVideo
//
// Created by iOS Dev on 1/16/25.
//

import UIKit

final class FilterButton: UIButton {
private let height: CGFloat = 50.0
private let leftRightMargin: CGFloat = 70.0
private var title = ""

init(title: String) {
super.init(frame: .zero)

self.title = title
self.setTitle(title, for: .normal)
self.layer.cornerRadius = height / 2
}

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

func width() -> CGFloat {
let titleWidth = title.width(size: 20)
return titleWidth + leftRightMargin
}

func updateState() {
if isSelected {
changeColor(title: .buttonSelectedText, background: .buttonSelectedBackground)
} else {
changeColor(title: .buttonDefaultText, background: .buttonDefaultBackground)
}
}

private func changeColor(title: UIColor, background: UIColor) {
self.setTitleColor(title, for: .normal)
self.backgroundColor = background
}
}
45 changes: 45 additions & 0 deletions TodayVideo/TodayVideo/Common/NextButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// NextButton.swift
// TodayVideo
//
// Created by iOS Dev on 1/16/25.
//

import UIKit
import SnapKit

final class NextButton: UIButton {
private var currentView: UIViewController!

init(location: UIViewController) {
super.init(frame: .zero)

self.currentView = location
self.setImage(.nextButton, for: .normal)
self.addTarget(self, action: #selector(pushToNextView), for: .touchUpInside)
self.currentView.view.addSubview(self)
self.layout(in: currentView.view)
}

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

func layout(in view: UIView) {
self.snp.makeConstraints { make in
make.width.equalTo(15.4)
make.height.equalTo(23)
make.trailing.equalTo(view.snp.trailing).offset(-41.6)
make.bottom.equalTo(view.snp.bottom).offset(-78)
}
}

@objc private func pushToNextView() {
switch currentView {
case is ContentView:
guard let contentView = currentView as? ContentView else { return }
contentView.presenter?.pushToGenreView()
default: break
}
}
}
22 changes: 22 additions & 0 deletions TodayVideo/TodayVideo/ContentView/ContentPresenter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// ContentPresenter.swift
// TodayVideo
//
// Created by iOS Dev on 1/15/25.
//

import Foundation

protocol ContentPresenterProtocol {
func pushToGenreView()
}

final class ContentPresenter: ContentPresenterProtocol {
var router: ContentRouterProtocol?

func pushToGenreView() {
DispatchQueue.main.async {
self.router?.pushToGenreView()
}
}
}
35 changes: 35 additions & 0 deletions TodayVideo/TodayVideo/ContentView/ContentRouter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// ContentRouter.swift
// TodayVideo
//
// Created by iOS Dev on 1/15/25.
//

import UIKit

protocol ContentRouterProtocol {
func pushToGenreView()
}

final class ContentRouter: ContentRouterProtocol {
weak var contentView: ContentView?

static func createContentViewModule() -> ContentView {
let view = ContentView()
let presenter = ContentPresenter()
let router = ContentRouter()

view.presenter = presenter
presenter.router = router
router.contentView = view

return view
}

// 장르 선택 화면으로 push
func pushToGenreView() {
// 다음 화면으로 이동을 위한 처리 코드 입니다.
// let genreView = GenreRouter.createGenre
// contentView?.navigationController?.pushViewController(genreView, animated: true)
Comment on lines +32 to +33

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 올리실 때에는 임의 주석 처리한 코드는 정리해주시는 것이 좋습니다.

}
}
92 changes: 92 additions & 0 deletions TodayVideo/TodayVideo/ContentView/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// ContentView.swift
// TodayVideo
//
// Created by iOS Dev on 1/15/25.
//

import UIKit
import SnapKit

final class ContentView: UIViewController {
var presenter: ContentPresenterProtocol?

private var movieButton: FilterButton!
private var tvButton: FilterButton!
private let movie = "영화"
private let tv = "TV"
private lazy var selectedContent = movie

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selectedContent는 선택된 컨텐츠를 저장하는데 사용되지만, movieButtontvButton의 상태 변경에 따라 selectedContent가 변경되는 구조로 판단됩니다. 만약 나중에 선택된 콘텐츠에 따라 다른 처리가 필요하다면, selectedContentenum 타입으로 변경하기를 권장드립니다.


override func viewDidLoad() {
super.viewDidLoad()

drawUI()
buttonSelected(movieButton)
}

private func drawUI() {
self.view.backgroundColor = .background

// 영화, 드라마 버튼
/// 컨테이너
let height: CGFloat = 50.0
let containerView = UIView()
let containerViewWidth: CGFloat = 300.0

self.view.addSubview(containerView)

containerView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.height.equalTo(height)
make.width.equalTo(containerViewWidth)
}

/// 버튼
movieButton = FilterButton(title: movie)
tvButton = FilterButton(title: tv)

[movieButton, tvButton].forEach { button in
button.addTarget(self, action: #selector(buttonSelected(_:)), for: .touchUpInside)
containerView.addSubview(button)
}

let margin: CGFloat = 8.0
let buttonWidth = (containerViewWidth / 2) - margin

movieButton.snp.makeConstraints { make in
make.left.top.bottom.equalToSuperview()
make.width.equalTo(buttonWidth)
}

tvButton.snp.makeConstraints { make in
make.right.top.bottom.equalToSuperview()
make.width.equalTo(buttonWidth)
}

// 다음 버튼
let _ = NextButton(location: self)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분이 잘 이해가지 않네요. 할당하지 않는데 왜 생성되었을까요?

}

@objc private func buttonSelected(_ sender: UIButton) {
// 이미 선택되어 있는 버튼이면 return
if sender.isSelected {
return
}

sender.isSelected = !sender.isSelected

DispatchQueue.main.async {
if sender == self.movieButton {
self.selectedContent = self.movie
self.tvButton.isSelected = false
self.tvButton.updateState()
self.movieButton.updateState()
} else {
self.selectedContent = self.tv
self.movieButton.isSelected = false
self.movieButton.updateState()
self.tvButton.updateState()
}
}
}
}
16 changes: 16 additions & 0 deletions TodayVideo/TodayVideo/Extension/String+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// String+Extension.swift
// TodayVideo
//
// Created by iOS Dev on 1/17/25.
//

import UIKit

extension String {
func width(size: CGFloat) -> CGFloat {
let font = UIFont.systemFont(ofSize: size)
let attributes: [NSAttributedString.Key: Any] = [.font: font]
return self.size(withAttributes: attributes).width
}
}
5 changes: 5 additions & 0 deletions TodayVideo/TodayVideo/Extension/UIColor+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ extension UIColor {
static let title1 = UIColor(hex: "#4AFFF3") ?? .red
static let title2 = UIColor(hex: "#264CA5") ?? .red
static let title3 = UIColor(hex: "#000000") ?? .black
// ContentView
static let buttonDefaultBackground = UIColor(hex: "#1E2122") ?? .gray
static let buttonDefaultText = UIColor(hex: "#FDFDFD") ?? .white
static let buttonSelectedBackground = UIColor(hex: "#3B84A8") ?? .blue
static let buttonSelectedText = UIColor(hex: "#1E2122") ?? .black
}

extension UIColor {
Expand Down
12 changes: 12 additions & 0 deletions TodayVideo/TodayVideo/Extension/UIImage+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// UIImage+Extension.swift
// TodayVideo
//
// Created by iOS Dev on 1/16/25.
//

import UIKit

extension UIImage {
static let nextButton = UIImage(named: "next")
}
Loading
Loading