Skip to content

Commit

Permalink
Merge pull request #237 from Team-Smeme/chore/#233-DeviceRatio
Browse files Browse the repository at this point in the history
[Chore] #233 - EditDiaryView 래핑 및 기기대응 코드 개선
  • Loading branch information
joonBaek12 authored Dec 10, 2024
2 parents 6b71fbb + f60fc15 commit 4b628b9
Show file tree
Hide file tree
Showing 14 changed files with 522 additions and 247 deletions.
60 changes: 45 additions & 15 deletions Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions Smeem-iOS/Smeem-iOS/Global/Extensions/Double+.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Double+.swift
// Smeem-iOS
//
// Created by Joon Baek on 12/1/24.
//

import UIKit

extension Double {
// 너비 기반 스케일링 (iPhone 13 mini)
func scaledByWidth() -> Double {
return (self / 375) * UIScreen.main.bounds.width
}

// 높이 기반 스케일링 (iPhone 13 mini)
func scaledByHeight() -> Double {
return (self / 812) * UIScreen.main.bounds.height
}
}
66 changes: 65 additions & 1 deletion Smeem-iOS/Smeem-iOS/Global/Extensions/SwiftUI/View+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,82 @@ extension View {
}

var screenHeight: Double {
return screenSize.height
return screenSize.height
}

var screenWidth: Double {
return screenSize.width
}

func showEditConfirmation(
title: String,
message: String,
firstActionTitle: String,
secondActionTitle: String,
firstActionHandler: (() -> Void)? = nil,
secondActionHandler: (() -> Void)? = nil
) {
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: .alert
)

alert.addAction(UIAlertAction(title: firstActionTitle, style: .cancel) { _ in
firstActionHandler?()
})

alert.addAction(UIAlertAction(title: secondActionTitle, style: .default) { _ in
secondActionHandler?()
})

if let topViewController = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
topViewController.present(alert, animated: true)
}
}

func changeRootViewController(_ viewController: UIViewController) {
guard let window = UIApplication.shared.windows.first else { return }
UIView.transition(with: window, duration: 0.5, options: .transitionCrossDissolve, animations: {
let rootVC = UINavigationController(rootViewController: viewController)
window.rootViewController = rootVC
})
}

func pushToUIKitView(_ viewController: UIViewController, dismissFullScreenCover: Bool = true) {
// 현재 presenting된 view controller
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootViewController = windowScene.windows.first?.rootViewController {

// 현재 최상위 view controller (fullScreenCover 아래의 view controller)
var topViewController = rootViewController
while let presentedViewController = topViewController.presentedViewController {
topViewController = presentedViewController
}

if let navigationController = topViewController as? UINavigationController {
navigationController.pushViewController(viewController, animated: true)

if dismissFullScreenCover,
let presentingView = topViewController.presentingViewController {
presentingView.dismiss(animated: false, completion: nil)
}
}
}
}

func changeRootViewControllerAndPresent(_ viewControllerToPresent: UIViewController) {
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first {

window.rootViewController = viewControllerToPresent

UIView.transition(with: window,
duration: 0.5,
options: .transitionCrossDissolve,
animations: nil)

window.makeKeyAndVisible()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

import SwiftUI

import SwiftUI

struct CoachingComparisonView: View {
@Binding var coachingResponse: CoachingResponse

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,62 @@
// Created by Joon Baek on 11/21/24.
//

//import SwiftUI
import SwiftUI

struct CoachingContentView: View {
@Binding var currentIndex: Int
@Binding var coachingsResponse: CoachingsResponse
@Binding var coachingResponse: [CoachingResponse]

var body: some View {
VStack(spacing: 20.scaledByHeight()) {
Rectangle()
.frame(height: 8.scaledByHeight())
.foregroundStyle(Color(UIColor.gray100))

TabView(selection: $currentIndex) {
ForEach(coachingResponse.indices, id: \.self) { item in
ScrollView {
VStack(spacing: 8.scaledByHeight()) {
CoachingComparisonView(coachingResponse: $coachingResponse[item])
CoachingExplanationView(coachingResponse: $coachingResponse[item])
}
}
}
}
.frame(width: screenWidth, height: screenHeight * (286 / screenHeight), alignment: .top)
.tabViewStyle(.page(indexDisplayMode: .never))
.padding(.horizontal, 16.scaledByWidth())

PageControl(currentPage: $currentIndex, coachingResponse: $coachingResponse)
}
}
}

#Preview {
@State var defaultIndex: Int = 0
@State var coachingsResponse = CoachingsResponse.empty
@State var coachingResponse = CoachingsResponse.empty.corrections
CoachingContentView(currentIndex: $defaultIndex, coachingsResponse: $coachingsResponse, coachingResponse: $coachingResponse)
}

//
//struct CoachingContentView: View {
// @Binding var currentIndex: Int
// @Binding var coachingResponse: CoachingsResponse
//
//
// var body: some View {
// VStack(spacing: screenHeight * (20 / screenHeight)) {
// Rectangle()
// .frame(height: screenHeight * (8 / screenHeight))
// .foregroundStyle(Color(UIColor.gray100))
//
//
// TabView(selection: $currentIndex) {
// ForEach(coachingResponse.corrections.indices, id: \.self) { item in
// ScrollView {
// VStack(spacing: screenWidth * (8 / screenWidth)) {
// CoachingComparisonView(coachingResponse: $coachingResponse.corrections[item])
//
//
// CoachingExplanationView(coachingResponse: $coachingResponse.corrections[item])
// }
// }
Expand All @@ -31,7 +69,7 @@
// .frame(width: screenWidth, height: screenHeight * (286 / screenHeight), alignment: .top)
// .tabViewStyle(.page(indexDisplayMode: .never))
// .padding(.horizontal, screenWidth * (16 / screenWidth))
//
//
// PageControl(currentPage: $currentIndex,
// coachingResponse: $coachingResponse)
// }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,59 +16,148 @@ struct CustomSegmentedControl: View {
ForEach(options.indices, id: \.self) { index in
SegmentButton(
title: options[index],
isSelected: selectedIndex == index,
isSelected: isCoachingOn(index),
isFirstButton: index == 0,
isLastButton: index == options.count - 1,
action: { selectedIndex = index }
)
}
}
.background(Color.gray.opacity(0.2))
.cornerRadius(8)
.cornerRadius(6)
}

private func isCoachingOn(_ index: Int) -> Bool {
// "코칭 ON"일 때만 selected 상태로 처리
return options[index] == "코칭 ON" && selectedIndex == index
}
}

struct SegmentButton: View {
let title: String
let isSelected: Bool
let isFirstButton: Bool
let isLastButton: Bool
let action: () -> Void

var body: some View {
Button(action: action) {
Text(title)
.padding(.vertical, 8)
.padding(.horizontal, 11)
.padding(.vertical, 8.scaledByHeight())
.padding(.horizontal, 11.scaledByWidth())
.frame(maxWidth: .infinity)
.background(backgroundColor)
.foregroundColor(foregroundColor)
.font(Font(UIFont.c5))
.overlay(
Group {
// 'isSelected'일 때만 'isFirstButton'에 오버레이 추가
if isSelected && isFirstButton {
CustomStrokeShape(includeLeadingCorners: false)
.stroke(Color(UIColor.gray500), lineWidth: 1)
} else if !isSelected {
// 'isSelected'가 아닐 때는 모든 버튼에 대해 모서리 처리
CustomStrokeShape(
includeLeadingCorners: isFirstButton,
includeTrailingCorners: isLastButton
)
.stroke(Color(UIColor.gray500), lineWidth: 1)
}
}
)
}
}

private var backgroundColor: Color {
isSelected ? (isCoachingOn ? Color(UIColor.point) : Color(UIColor.gray200)) : Color(UIColor.gray100)
isSelected ? Color(UIColor.point) : isFirstButton ? Color(UIColor.gray100) : Color(UIColor.white)
}

private var foregroundColor: Color {
isSelected ? .white : Color(UIColor.gray500)
isSelected ? Color(UIColor.smeemWhite) : Color(UIColor.gray500)
}

private var isCoachingOn: Bool {
title == "코칭 ON"
}
}

struct PreviewWrapper: View {
@State private var selectedIndex = 0
let options = ["코칭 OFF", "코칭 ON"]
struct CustomStrokeShape: Shape {
var radius: CGFloat = 6
var includeLeadingCorners: Bool = true
var includeTrailingCorners: Bool = true

var body: some View {
CustomSegmentedControl(selectedIndex: $selectedIndex, options: options)
.frame(height: 40)
.padding(117)
func path(in rect: CGRect) -> Path {
var path = Path()

// Move to the starting point (TopLeading)
path.move(to: CGPoint(x: rect.minX + (includeLeadingCorners ? radius : 0), y: rect.minY))

// TopLeading Corner
if includeLeadingCorners {
path.addArc(
center: CGPoint(x: rect.minX + radius, y: rect.minY + radius),
radius: radius,
startAngle: .degrees(-90),
endAngle: .degrees(180),
clockwise: true
)
} else {
path.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
}

// BottomLeading Corner
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY - (includeLeadingCorners ? radius : 0)))
if includeLeadingCorners {
path.addArc(
center: CGPoint(x: rect.minX + radius, y: rect.maxY - radius),
radius: radius,
startAngle: .degrees(180),
endAngle: .degrees(90),
clockwise: true
)
} else {
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
}

// BottomTrailing Corner
path.addLine(to: CGPoint(x: rect.maxX - (includeTrailingCorners ? radius : 0), y: rect.maxY))
if includeTrailingCorners {
path.addArc(
center: CGPoint(x: rect.maxX - radius, y: rect.maxY - radius),
radius: radius,
startAngle: .degrees(90),
endAngle: .degrees(0),
clockwise: true
)
} else {
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
}

// TopTrailing Corner
path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY + (includeTrailingCorners ? radius : 0)))
if includeTrailingCorners {
path.addArc(
center: CGPoint(x: rect.maxX - radius, y: rect.minY + radius),
radius: radius,
startAngle: .degrees(0),
endAngle: .degrees(-90),
clockwise: true
)
} else {
path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
}

path.closeSubpath()
return path
}
}

@available(iOS 17.0, *)
#Preview {
PreviewWrapper()
@State var selectedIndex = 1
let options = ["코칭 OFF", "코칭 ON"]

CustomSegmentedControl(selectedIndex: $selectedIndex, options: options)
.frame(height: 32.scaledByHeight())
.padding(117.scaledByWidth())
}

Loading

0 comments on commit 4b628b9

Please sign in to comment.