Skip to content

Commit c9f7a9d

Browse files
Merge pull request #347 from BCSDLab/chore/lostitem
chore: 분실물 QA 사소한 디자인 변경
2 parents f6c9995 + af2a7d5 commit c9f7a9d

8 files changed

Lines changed: 147 additions & 47 deletions

File tree

Koin/Core/Extensions/UIViewController+.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import UIKit.UIViewController
99

1010
extension UIViewController {
11-
func hideKeyboardWhenTappedAround() {
11+
@objc func hideKeyboardWhenTappedAround() {
1212
let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
1313
tap.cancelsTouchesInView = false
1414
view.addGestureRecognizer(tap)

Koin/Presentation/Home/Home/SubViews/LostItemListView.swift

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,22 @@ final class LostItemListView: UIView {
2323
$0.font = UIFont.appFont(.pretendardBold, size: 15)
2424
}
2525

26-
private let chevronButton = UIButton().then {
27-
$0.setImage(UIImage(named: "chevronRightBlue")?.withRenderingMode(.alwaysTemplate), for: .normal)
28-
$0.tintColor = UIColor(hexCode: "1C1B1F")
29-
}
30-
3126
private let descriptionButton = UIButton().then {
3227
$0.backgroundColor = .appColor(.neutral100)
3328
$0.layer.cornerRadius = 8
3429
$0.clipsToBounds = true
3530
}
3631

32+
private let descriptionLabel = UILabel().then {
33+
$0.font = .appFont(.pretendardMedium, size: 14)
34+
$0.textColor = .appColor(.neutral800)
35+
}
36+
37+
private let chevronImageView = UIImageView(image: .appImage(asset: .chevronRightBlue)?.withTintColor(UIColor(hexCode: "1C1B1F"))
38+
)
39+
40+
41+
3742
// MARK: - Initializer
3843
init() {
3944
super.init(frame: .zero)
@@ -47,16 +52,25 @@ final class LostItemListView: UIView {
4752
func configure(lostItemStats: LostItemStats) {
4853
foundCountTitle = "지금까지 \(lostItemStats.foundCount)명이 분실물을 찾았어요."
4954
notFoundCountTitle = "\(lostItemStats.notFoundCount)개의 분실물이 주인을 찾고있어요."
50-
descriptionButton.setAttributedTitle(NSAttributedString(
51-
string: notFoundCountTitle,
52-
attributes: [
53-
.font : UIFont.appFont(.pretendardMedium, size: 14),
54-
.foregroundColor : UIColor.appColor(.neutral800)
55-
]), for: .normal
56-
)
55+
56+
let longerTitle: String
57+
foundCountTitle.count < notFoundCountTitle.count ? (longerTitle = notFoundCountTitle) : (longerTitle = foundCountTitle)
58+
59+
descriptionLabel.text = longerTitle
60+
61+
descriptionLabel.snp.remakeConstraints {
62+
$0.center.equalTo(descriptionButton)
63+
$0.width.equalTo(descriptionLabel.intrinsicContentSize.width)
64+
}
65+
chevronImageView.snp.remakeConstraints {
66+
$0.centerY.equalTo(descriptionLabel)
67+
$0.leading.equalTo(descriptionLabel.snp.trailing).offset(8)
68+
}
5769

5870
if 50 <= lostItemStats.foundCount {
5971
setTimer()
72+
} else {
73+
descriptionLabel.text = notFoundCountTitle
6074
}
6175
}
6276
}
@@ -73,24 +87,16 @@ extension LostItemListView {
7387
$0.type = .push
7488
$0.subtype = .fromTop
7589
}
76-
descriptionButton.titleLabel?.layer.add(transition, forKey: "newTitle")
90+
descriptionLabel.layer.add(transition, forKey: "newTitle")
7791

78-
let newTitle = descriptionButton.titleLabel?.text == notFoundCountTitle ? foundCountTitle : notFoundCountTitle
92+
let newTitle = descriptionLabel.text == notFoundCountTitle ? foundCountTitle : notFoundCountTitle
7993

80-
descriptionButton.setAttributedTitle(NSAttributedString(
81-
string: newTitle,
82-
attributes: [
83-
.font : UIFont.appFont(.pretendardMedium, size: 14),
84-
.foregroundColor : UIColor.appColor(.neutral800)
85-
]), for: .normal
86-
)
94+
descriptionLabel.text = newTitle
8795
}
8896
}
8997

9098
private func setAddTargets() {
91-
[chevronButton, descriptionButton].forEach {
92-
$0.addTarget(self, action: #selector(lostItemListTapped), for: .touchUpInside)
93-
}
99+
descriptionButton.addTarget(self, action: #selector(lostItemListTapped), for: .touchUpInside)
94100
}
95101
@objc private func lostItemListTapped() {
96102
lostItemListTappedPublisher.send()
@@ -99,7 +105,7 @@ extension LostItemListView {
99105
extension LostItemListView {
100106

101107
private func setLayouts() {
102-
[nameLabel, chevronButton, descriptionButton].forEach {
108+
[nameLabel, descriptionButton, descriptionLabel, chevronImageView].forEach {
103109
addSubview($0)
104110
}
105111
}
@@ -108,17 +114,19 @@ extension LostItemListView {
108114
$0.top.equalToSuperview()
109115
$0.leading.equalToSuperview().offset(20)
110116
}
111-
chevronButton.snp.makeConstraints {
112-
$0.centerY.equalTo(nameLabel)
113-
$0.trailing.equalToSuperview().offset(-24)
114-
$0.size.equalTo(29)
115-
}
116117
descriptionButton.snp.makeConstraints {
117118
$0.top.equalTo(nameLabel.snp.bottom).offset(16)
118119
$0.leading.trailing.equalToSuperview().inset(24)
119120
$0.height.equalTo(44)
120121
$0.bottom.equalToSuperview()
121122
}
123+
descriptionLabel.snp.makeConstraints {
124+
$0.center.equalTo(descriptionButton)
125+
}
126+
chevronImageView.snp.makeConstraints {
127+
$0.centerY.equalTo(descriptionLabel)
128+
$0.centerX.equalTo(descriptionLabel).offset(100)
129+
}
122130
}
123131
private func configureView() {
124132
setLayouts()

Koin/Presentation/LostItem/EditLostItem/EditLostItemViewController.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ final class EditLostItemViewController: UIViewController {
8787
configureNavigationBar(style: .empty)
8888
}
8989

90+
override func hideKeyboardWhenTappedAround() {
91+
super.hideKeyboardWhenTappedAround()
92+
foundDateView.dismissDropdown()
93+
}
94+
9095
private func bind() {
9196
viewModel.transform(with: inputSubject.eraseToAnyPublisher()).sink { [weak self] output in
9297
guard let self else { return }
@@ -120,6 +125,13 @@ final class EditLostItemViewController: UIViewController {
120125
contentView.shouldDismissDropDownPublisher.sink { [weak self] in
121126
self?.foundDateView.dismissDropdown()
122127
}.store(in: &subscriptions)
128+
129+
foundDateView.focusDropdownPublisher.sink { [weak self] targetView in
130+
guard let self else { return }
131+
var rect = targetView.convert(targetView.bounds, to: scrollView)
132+
rect.size.height += 15
133+
scrollView.scrollRectToVisible(rect, animated: true)
134+
}.store(in: &subscriptions)
123135
}
124136
}
125137

@@ -130,6 +142,9 @@ extension EditLostItemViewController {
130142
}
131143

132144
@objc private func editButtonTapped() {
145+
dismissKeyboard()
146+
foundDateView.dismissDropdown()
147+
133148
if foundDateView.isValid && foundPlaceView.isValid {
134149
let imageUrls = imagesView.imageUploadCollectionView.imageUrls
135150
let category = categoryView.selectedCategory

Koin/Presentation/LostItem/EditLostItem/SubViews/EditLostItemFoundDateView.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ final class EditLostItemFoundDateView: ExtendedTouchAreaView {
1818
dateWarningLabel.isHidden
1919
}
2020
private(set) var foundDate: String
21+
let focusDropdownPublisher = PassthroughSubject<UIView, Never>()
2122

2223
// MARK: - UI Components
2324
private lazy var dateLabel = UILabel().then {
@@ -106,6 +107,9 @@ final class EditLostItemFoundDateView: ExtendedTouchAreaView {
106107
dropdownView.valueChangedPublisher.sink { [weak self] in
107108
self?.dropdownValueChanged()
108109
}.store(in: &subscriptions)
110+
dropdownView.dismissDropdownPublisher.sink { [weak self] in
111+
self?.dismissDropdown()
112+
}.store(in: &subscriptions)
109113
}
110114

111115
private func setAddTargets() {
@@ -116,6 +120,7 @@ final class EditLostItemFoundDateView: ExtendedTouchAreaView {
116120
if dropdownView.isHidden {
117121
presentDropdown()
118122
endEditing(true)
123+
focusDropdownPublisher.send(dropdownView)
119124
} else {
120125
dismissDropdown()
121126
}
@@ -134,7 +139,7 @@ final class EditLostItemFoundDateView: ExtendedTouchAreaView {
134139
}
135140

136141
@objc func dismissDropdown() {
137-
UIView.animate(withDuration: 0.1) { [weak self] in
142+
UIView.animate(withDuration: 0.2) { [weak self] in
138143
guard let self else { return }
139144
dropdownView.alpha = 0
140145
dropdownView.transform = CGAffineTransform(translationX: 0, y: -20)

Koin/Presentation/LostItem/EditLostItem/SubViews/EditLostItemFoundPlaceView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ final class EditLostItemFoundPlaceView: UIView {
7575
locationTextField.textColor = .appColor(.neutral500)
7676
}
7777

78+
if type == .lost {
79+
essentialLabel.isHidden = true
80+
}
81+
7882
configureView()
7983
setAddTargets()
8084
setDelegate()

Koin/Presentation/LostItem/PostLostItem/PostLostItemViewController.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ extension PostLostItemViewController: UITextViewDelegate, PHPickerViewController
187187
return allCellData
188188
}
189189
private func writeButtonTapped() {
190+
dismissKeyboardDropdown()
191+
190192
var isAllValid = true
191193
for index in 0..<addLostItemCollectionView.numberOfItems(inSection: 0) {
192194
let indexPath = IndexPath(item: index, section: 0)

Koin/Presentation/LostItem/PostLostItem/SubViews/AddLostItemCollectionView/AddLostItemCollectionViewCell.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ final class AddLostItemCollectionViewCell: UICollectionViewCell {
224224
dropdownView.valueChangedPublisher.sink { [weak self] in
225225
self?.dropdownValueChanged()
226226
}.store(in: &cancellable)
227+
dropdownView.dismissDropdownPublisher.sink { [weak self] in
228+
self?.shouldDismissDropDownPublisher.send(nil)
229+
}.store(in: &cancellable)
227230
}
228231
required init?(coder: NSCoder) {
229232
fatalError("init(coder:) has not been implemented")
@@ -609,8 +612,7 @@ extension AddLostItemCollectionViewCell: UITextFieldDelegate {
609612
extension AddLostItemCollectionViewCell {
610613

611614
private func setUpLayouts() {
612-
[separateView, itemCountLabel, pictureLabel, pictureMessageLabel, pictureCountLabel, addPictureButton, categoryLabel, categoryMessageLabel, categoryStackView, dateLabel, locationLabel, locationTextField, contentLabel, contentTextCountLabel, contentTextView, deleteCellButton, categoryWarningLabel, dateWarningLabel, locationWarningLabel, imageUploadCollectionView, dropdownView, dateButton, categoryEssentialLabel, dateEssentialLabel, locationEssentialLabel
613-
].forEach {
615+
[separateView, itemCountLabel, pictureLabel, pictureMessageLabel, pictureCountLabel, addPictureButton, categoryLabel, categoryMessageLabel, categoryStackView, dateLabel, locationLabel, locationTextField, contentLabel, contentTextCountLabel, contentTextView, deleteCellButton, categoryWarningLabel, dateWarningLabel, locationWarningLabel, imageUploadCollectionView, categoryEssentialLabel, dateEssentialLabel, locationEssentialLabel, dropdownView, dateButton].forEach {
614616
contentView.addSubview($0)
615617
}
616618
dateButton.addSubview(chevronImage)

Koin/Presentation/LostItem/PostLostItem/SubViews/DatePickerDropdownView.swift

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,109 @@
77

88
import UIKit
99
import Combine
10+
import SnapKit
1011

1112
final class DatePickerDropdownView: UIView {
1213

14+
// MARK: - Properties
1315
let valueChangedPublisher = PassthroughSubject<Void, Never>()
16+
let dismissDropdownPublisher = PassthroughSubject<Void, Never>()
17+
1418
var dateValue: Date {
1519
get { return datePicker.date }
1620
set { datePicker.date = newValue }
1721
}
1822

23+
// MARK: - UI Components
1924
private let datePicker = UIDatePicker().then {
2025
$0.datePickerMode = .date
2126
$0.preferredDatePickerStyle = .wheels
2227
$0.locale = Locale(identifier: "ko_KR")
2328
$0.minimumDate = Calendar.current.date(byAdding: .year, value: -10, to: Date())
2429
$0.maximumDate = Date()
2530
}
31+
private let separatorView = UIView().then {
32+
$0.backgroundColor = .appColor(.neutral200)
33+
}
34+
private let resetButton = UIButton().then {
35+
$0.setAttributedTitle(NSAttributedString(
36+
string: "초기화",
37+
attributes: [
38+
.font : UIFont.appFont(.pretendardMedium, size: 14),
39+
.foregroundColor : UIColor.appColor(.primary600)
40+
]), for: .normal)
41+
}
42+
private let applyButton = UIButton().then {
43+
$0.setAttributedTitle(NSAttributedString(
44+
string: "확인",
45+
attributes: [
46+
.font : UIFont.appFont(.pretendardMedium, size: 14),
47+
.foregroundColor : UIColor.appColor(.primary600)
48+
]), for: .normal)
49+
}
2650

27-
var onDateSelected: ((Date) -> Void)?
28-
51+
// MARK: - Initializer
2952
override init(frame: CGRect) {
3053
super.init(frame: frame)
31-
setupView()
54+
configureView()
55+
setAddTargets()
3256
datePicker.addTarget(self, action: #selector(datePickerValueChagned), for: .valueChanged)
3357
}
3458

3559
required init?(coder: NSCoder) {
3660
fatalError("init(coder:) has not been implemented")
3761
}
62+
}
63+
64+
extension DatePickerDropdownView {
65+
66+
private func setAddTargets() {
67+
resetButton.addTarget(self, action: #selector(resetButtonTapped), for: .touchUpInside)
68+
applyButton.addTarget(self, action: #selector(applyButtonTapped), for: .touchUpInside)
69+
}
70+
71+
@objc private func resetButtonTapped() {
72+
dateValue = Date()
73+
datePickerValueChagned()
74+
}
75+
76+
@objc private func applyButtonTapped() {
77+
dismissDropdownPublisher.send()
78+
}
79+
}
80+
81+
extension DatePickerDropdownView {
82+
83+
private func setUpLayouts() {
84+
[datePicker, separatorView, applyButton, resetButton].forEach {
85+
addSubview($0)
86+
}
87+
}
88+
private func setUpConstraints() {
89+
datePicker.snp.makeConstraints {
90+
$0.top.leading.trailing.equalToSuperview()
91+
$0.height.equalTo(114)
92+
}
93+
separatorView.snp.makeConstraints {
94+
$0.top.equalTo(datePicker.snp.bottom)
95+
$0.leading.trailing.equalToSuperview()
96+
$0.height.equalTo(1)
97+
}
98+
applyButton.snp.makeConstraints {
99+
$0.top.equalTo(separatorView.snp.bottom).offset(10)
100+
$0.trailing.equalToSuperview().offset(-40)
101+
$0.bottom.equalToSuperview().offset(-14)
102+
$0.height.equalTo(22)
103+
}
104+
resetButton.snp.makeConstraints {
105+
$0.height.centerY.equalTo(applyButton)
106+
$0.trailing.equalTo(applyButton.snp.leading).offset(-16)
107+
}
108+
}
38109

39-
private func setupView() {
40-
addSubview(datePicker)
41-
datePicker.translatesAutoresizingMaskIntoConstraints = false
42-
NSLayoutConstraint.activate([
43-
datePicker.leadingAnchor.constraint(equalTo: leadingAnchor),
44-
datePicker.trailingAnchor.constraint(equalTo: trailingAnchor),
45-
datePicker.topAnchor.constraint(equalTo: topAnchor),
46-
datePicker.bottomAnchor.constraint(equalTo: bottomAnchor),
47-
heightAnchor.constraint(equalToConstant: 114)
48-
])
110+
private func configureView(){
111+
setUpLayouts()
112+
setUpConstraints()
49113

50114
DispatchQueue.main.async {
51115
self.updatePickerTextColor()

0 commit comments

Comments
 (0)