From c17e5139849c4df249d50924930c651d8ad815fe Mon Sep 17 00:00:00 2001 From: SeungHyun Hong Date: Wed, 19 Jun 2024 23:07:37 +0900 Subject: [PATCH 1/2] :construction: Add BottomSheetHeightPreferenceKey --- .../PreferenceKeys/BottomSheetHeightKey.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 PyeonHaeng-iOS/Sources/PreferenceKeys/BottomSheetHeightKey.swift diff --git a/PyeonHaeng-iOS/Sources/PreferenceKeys/BottomSheetHeightKey.swift b/PyeonHaeng-iOS/Sources/PreferenceKeys/BottomSheetHeightKey.swift new file mode 100644 index 0000000..98f4627 --- /dev/null +++ b/PyeonHaeng-iOS/Sources/PreferenceKeys/BottomSheetHeightKey.swift @@ -0,0 +1,17 @@ +// +// BottomSheetHeightKey.swift +// PyeonHaeng-iOS +// +// Created by 홍승현 on 6/19/24. +// + +import SwiftUI + +/// 바텀시트의 동적 높이를 계산하기 위한 PreferenceKey입니다. +struct BottomSheetHeightKey: PreferenceKey { + static var defaultValue: CGFloat = .zero + + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + value = nextValue() + } +} From a7d73993cb72ec5ac86f2b077efd7bf29e731972 Mon Sep 17 00:00:00 2001 From: SeungHyun Hong Date: Wed, 19 Jun 2024 23:23:41 +0900 Subject: [PATCH 2/2] :sparkles: Implement dynamic bottom sheet height view --- PyeonHaeng-iOS.xcodeproj/project.pbxproj | 12 +++++++ .../View/HomeProductDetailSelectionView.swift | 33 ++++++++++++++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/PyeonHaeng-iOS.xcodeproj/project.pbxproj b/PyeonHaeng-iOS.xcodeproj/project.pbxproj index 2ca4fb0..5881c49 100644 --- a/PyeonHaeng-iOS.xcodeproj/project.pbxproj +++ b/PyeonHaeng-iOS.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ BAAF1D302BAFF1920001EA36 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BAAF1D2F2BAFF1920001EA36 /* Preview Assets.xcassets */; }; BAAF1D3A2BB01D910001EA36 /* NoticeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAAF1D392BB01D910001EA36 /* NoticeDetailView.swift */; }; BAAF1D3C2BB01D980001EA36 /* NoticeDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAAF1D3B2BB01D980001EA36 /* NoticeDetailViewModel.swift */; }; + BAB254A02C2315F900E74438 /* BottomSheetHeightKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB2549F2C2315F900E74438 /* BottomSheetHeightKey.swift */; }; BAB569612B639F3000D1E0F9 /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = BAB569602B639F3000D1E0F9 /* DesignSystem */; }; BAB5CF252B6B7C5A008B24BF /* Services.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB5CF242B6B7C5A008B24BF /* Services.swift */; }; BAB5CF272B6B7CF3008B24BF /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB5CF262B6B7CF3008B24BF /* HomeViewModel.swift */; }; @@ -159,6 +160,7 @@ BAAF1D2F2BAFF1920001EA36 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; BAAF1D392BB01D910001EA36 /* NoticeDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeDetailView.swift; sourceTree = ""; }; BAAF1D3B2BB01D980001EA36 /* NoticeDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeDetailViewModel.swift; sourceTree = ""; }; + BAB2549F2C2315F900E74438 /* BottomSheetHeightKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetHeightKey.swift; sourceTree = ""; }; BAB5CF242B6B7C5A008B24BF /* Services.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Services.swift; sourceTree = ""; }; BAB5CF262B6B7CF3008B24BF /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; BAB720332B9325F200C2CA1A /* PromotionSelectBottomSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromotionSelectBottomSheetView.swift; sourceTree = ""; }; @@ -296,6 +298,7 @@ BA28F1712B6152EE0052855E /* Sources */ = { isa = PBXGroup; children = ( + BAB2549E2C2315E600E74438 /* PreferenceKeys */, BA9D943B2BF20EBA00E7C9F7 /* AccessibilityIdentifier.swift */, E5462C652B65677B00E9FDF2 /* PromotionTag.swift */, BAA4D9AC2B5A1795005999F8 /* PyeonHaengApp.swift */, @@ -526,6 +529,14 @@ path = "Preview Content"; sourceTree = ""; }; + BAB2549E2C2315E600E74438 /* PreferenceKeys */ = { + isa = PBXGroup; + children = ( + BAB2549F2C2315F900E74438 /* BottomSheetHeightKey.swift */, + ); + path = PreferenceKeys; + sourceTree = ""; + }; BAB8C3AB2BAC7A09003DF3CC /* LeaveReview */ = { isa = PBXGroup; children = ( @@ -853,6 +864,7 @@ BAAF1D3C2BB01D980001EA36 /* NoticeDetailViewModel.swift in Sources */, BAB8C3AD2BAC7A11003DF3CC /* LeaveReviewView.swift in Sources */, BA8E83242B8EF83B00FE968C /* ProductConfiguration.swift in Sources */, + BAB254A02C2315F900E74438 /* BottomSheetHeightKey.swift in Sources */, BAA4D9AD2B5A1795005999F8 /* PyeonHaengApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/View/HomeProductDetailSelectionView.swift b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/View/HomeProductDetailSelectionView.swift index 12ef890..4ae0b11 100644 --- a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/View/HomeProductDetailSelectionView.swift +++ b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/View/HomeProductDetailSelectionView.swift @@ -15,6 +15,7 @@ struct HomeProductDetailSelectionView: View where ViewModel: HomeView @EnvironmentObject private var viewModel: ViewModel @State private var convenienceStoreModalPresented = false @State private var promotionModalPresented = false + @State private var bottomSheetHeight: CGFloat = .zero var body: some View { HStack { @@ -42,7 +43,12 @@ struct HomeProductDetailSelectionView: View where ViewModel: HomeView .accessibilityHint("더블 탭하여 편의점을 선택하세요") .sheet(isPresented: $convenienceStoreModalPresented) { ConvenienceSelectBottomSheetView() - .bottomSheetPresentation(height: Metrics.convenienceBottomSheetHeight) + .presentationDetents([bottomSheetHeight == .zero ? .medium : .height(bottomSheetHeight)]) + .presentationCornerRadius(20) + .presentationBackground(.regularMaterial) + .heightChangePreference { height in + bottomSheetHeight = height + } } } @@ -78,7 +84,12 @@ struct HomeProductDetailSelectionView: View where ViewModel: HomeView } .sheet(isPresented: $promotionModalPresented) { PromotionSelectBottomSheetView() - .bottomSheetPresentation(height: Metrics.promotionBottomSheetHeight) + .presentationDetents([bottomSheetHeight == .zero ? .medium : .height(bottomSheetHeight)]) + .presentationCornerRadius(20) + .presentationBackground(.regularMaterial) + .heightChangePreference { height in + bottomSheetHeight = height + } } } @@ -106,11 +117,17 @@ private extension Promotion { } } -extension View { - func bottomSheetPresentation(height: CGFloat) -> some View { - presentationDetents([.height(height)]) - .presentationCornerRadius(20) - .presentationBackground(.regularMaterial) +private extension View { + func heightChangePreference(completion: @escaping (CGFloat) -> Void) -> some View { + overlay { + GeometryReader { geometry in + Color.clear + .preference(key: BottomSheetHeightKey.self, value: geometry.size.height) + .onPreferenceChange(BottomSheetHeightKey.self) { value in + completion(value) + } + } + } } } @@ -130,6 +147,4 @@ private enum Metrics { static let promotionButtonCornerRadius: CGFloat = 16 static let height: CGFloat = 56 - static let convenienceBottomSheetHeight: CGFloat = 334 - static let promotionBottomSheetHeight: CGFloat = 238 }