Skip to content

Comments

Style/#365 나의여정 퀘스트 UI#372

Closed
y-eonee wants to merge 29 commits intodevelopfrom
style/#365-나의여정-ui

Hidden character warning

The head ref may contain hidden characters: "style/#365-\ub098\uc758\uc5ec\uc815-ui"
Closed

Style/#365 나의여정 퀘스트 UI#372
y-eonee wants to merge 29 commits intodevelopfrom
style/#365-나의여정-ui

Conversation

@y-eonee
Copy link
Collaborator

@y-eonee y-eonee commented Feb 22, 2026

🔗 연결된 이슈

📄 작업 내용

  • 퀘스트 관련 UI를 전반적으로 리팩토링하고 변경사항을 반영했습니다.
  • 공통 여정도 같은 뷰를 사용할 예정입니다. 분기처리는 승준오빠꺼 머지되면 할게요!!
  • 변경사항을 반영하면서 삭제된 파일이 있습니다. (Complete~View, Archive에서 사용되었던 컴포넌트들)
  • 또한 기존에 WriteQuest로 폴더가 분리되어있었는데, Quest 폴더에 하나로 통합했습니다.
  • 주리언니가 Archive에 버튼 만들어둔것은 .. 충돌 안날것 같긴 한데 나면 제가 해결하겠습니다!
구현 내용 퀘스트 작성 아카이브
GIF

💻 주요 코드 설명

키보드 대응

새롭게 바뀐 키보드 대응방식을 반영했습니다.

  1. 현재 포커스가 키보드에 가까워질 때, 뷰 높이가 그에 맞춰 조금씩 올라갑니다. => TextGrowth 함수
  2. 입력 중 키보드를 내리고, 다시 키보드를 열면 포커스된 위치에 맞추어 뷰가 내려가야합니다. => CaretRect 함수
    CaretRect은 저도 처음 알게 되었는데 현재 커서 위치의 삽입 좌표점이라고 합니다 !!
 private func adjustViewForTextGrowth(animated: Bool) {
        guard isKeyboardUsed else { return } // 키보드가 사용중인지 
        guard !keyboardFrameInWindow.isEmpty else { return }
        
        let currentHeight = rootView.questTextField.textView.bounds.height // 현재 입력중인 텍스트필드의 높이
        guard currentHeight > 0 else { return }
        
        if previousTextViewHeight == 0 { // 입력하지 않은 경우 
            previousTextViewHeight = currentHeight
            return
        }
        
        let diff = currentHeight - previousTextViewHeight // 현재 입력 중과 이전에 입력하던 뷰의 높이 차이 
        previousTextViewHeight = currentHeight 
        
        guard abs(diff) > 0.5 else { return } // 높이 변화 없다면 종료 

        let textView = rootView.questTextField.textView 
        let textViewFrameInWindow = textView.convert(textView.bounds, to: nil) // 내부 좌표계를 window좌표로 변환
        let keyboardTop = keyboardFrameInWindow.minY // keyboardTop을 기준으로 아래로 내려가면 키보드에 가려짐 
        let padding = 12.adjustedH

        let overlap = textViewFrameInWindow.maxY + padding - keyboardTop 
       // 텍스트뷰 아래 bottom 높이 + padding - 키보드 시작높이가 keyboardTop보다 크다면 키보드와 텍스트필드가 겹친것 

        let targetOffset = max(0, currentKeyboardOffset + overlap)

        guard abs(targetOffset - currentKeyboardOffset) > 0.5 else { return }
        currentKeyboardOffset = targetOffset
        
        UIView.animate(withDuration: 0.2) {
            self.rootView.transform = CGAffineTransform(translationX: 0, y: -self.currentKeyboardOffset)
        }
    }
    
    private func adjustViewForCurrentCaret(animated: Bool) {
        guard isKeyboardUsed else { return }
        guard !keyboardFrameInWindow.isEmpty else { return }
        
        let textView = rootView.questTextField.textView
        guard textView.isFirstResponder else { return }
        guard let selectedRange = textView.selectedTextRange else { return }
        
        let caretRect = textView.caretRect(for: selectedRange.end) // 현재 커서의 위치 
        let caretInWindow = textView.convert(caretRect, to: nil) // 윈도우 좌표계로 변환 
        let keyboardTop = keyboardFrameInWindow.minY
        let padding = 12.adjustedH
        
        let overlap = caretInWindow.maxY + padding - keyboardTop
        let targetOffset = max(0, overlap)
        
        guard abs(targetOffset - currentKeyboardOffset) > 0.5 else { return }
        currentKeyboardOffset = targetOffset
        
        UIView.animate(withDuration: 0.2) {
            self.rootView.transform = CGAffineTransform(translationX: 0, y: -self.currentKeyboardOffset)
        }
    }

여기 근데 맞는진 잘 모르겠어요.. 코드 더러워서 맘에 안듬...

UITextView 높이 동적대응

AS-IS

  • 텍스트 필드 내에서 스크롤이 가능했음.
  • height 고정

TO-BE

  • 최소 높이 지정
  • 최소 높이보다 내용을 더 많이 작성하게되면 뷰 높이가 늘어남. 이를 구현하기 위헤 UITextView 스크롤 불가 설정
func updateTextViewHeight() {
        let width = self.frame.width
        let fittingSize = CGSize(width: width, height: .greatestFiniteMagnitude) // 높이를 무한대로 열고 필요한 높이 계산 
        let estimatedHeight = ceil(textView.sizeThatFits(fittingSize).height) // 예상 높이 
        let containerMinHeight = 268.adjustedH
        let textViewMinHeight = 196.adjustedH
        
        containerHeightConsraint?.update(offset: max(containerMinHeight, estimatedHeight + 72.adjustedH)) // 72: 둘 사이 bottom offset이 72임 
        textViewHeightConstraint?.update(offset: max(textViewMinHeight, estimatedHeight))
        superview?.layoutIfNeeded()
        layoutIfNeeded()
    }
}

ByeBooNavigationBar 타입 추가

퀘스트 작성 부분의 네비게이션바 타입이 기존에는 없던 case여서 confirmAndBack 이라는 case를 추가했습니다.
또한, 텍스트의 bar Appearance를 지정해주었고, makeBarItem에 이미지 뿐만 아니라 String으로도 아이템을 만들 수 있도록 파라미터를 수정했습니다. 확장성있는 컴포넌트..개맹업개맹업

private static func makeBarButtonItem(
        image: UIImage? = nil, // 이미지와 String을 옵셔널로 지정했습니다. 
        title: String? = nil,
        target: BaseViewController,
        action: Selector?
    ) -> UIBarButtonItem {
        if let image {
            return UIBarButtonItem(
                image: image.withTintColor(.white).withRenderingMode(.alwaysOriginal),
                style: .plain,
                target: target,
                action: action
            )
        }
        
        if let title {
            return UIBarButtonItem(
                title: title,
                style: .plain,
                target: target,
                action: action
            )
        }
        
        return UIBarButtonItem( // 이건 오류 방지용 기본 리턴입니당 
            title: "기본",
            style: .plain,
            target: target,
            action: action
        )
    }

이에 따라 confirm Button을 텍스트필드에 입력된 값에 따라 update해주던 함수를 사용하지 않고, 대신 navigationItem에 접근하여 isEnabled를 t/f로 바꿔주는 방식을 사용합니다.

image

@y-eonee y-eonee linked an issue Feb 22, 2026 that may be closed by this pull request
1 task
@y-eonee y-eonee requested review from dev-domo and juri123123 and removed request for juri123123 February 22, 2026 18:07
@y-eonee y-eonee self-assigned this Feb 22, 2026
@y-eonee y-eonee requested a review from juri123123 February 22, 2026 18:07
@y-eonee y-eonee force-pushed the style/#365-나의여정-ui branch from 109b4bd to dc1ee8b Compare February 24, 2026 03:15
@y-eonee y-eonee closed this Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Style] 나의 여정 UI 변경사항 반영

1 participant