스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
SwiftUI로 macOS 윈도우 다듬기
macOS에 꼭 맞는 윈도우를 제작해 보세요. 목적, 사용 편의성, 기능 표현을 위해 앱의 윈도우를 정교하게 편집해 보세요. SwiftUI로 윈도우 도구 막대와 배경에 멋진 스타일을 적용해 보세요. 윈도우를 세밀하게 정렬하고, 복구 및 최소화에 스마트한 의사 결정 과정을 적용해 보세요.
챕터
- 0:53 - Anatomy of a window
- 1:53 - App window structure
- 2:41 - Style window toolbars
- 3:53 - Refine window behaviors
- 5:55 - Adjust window placement
리소스
- Customizing window styles and state-restoration behavior in macOS
- Destination Video
- Forum: UI Frameworks
- Windows
관련 비디오
WWDC24
WWDC22
-
다운로드
안녕하세요, 저는 Haotian이며 SwiftUI 팀의 엔지니어입니다 이 동영상에서는 새로운 SwiftUI API를 사용하여 macOS 애플리케이션 윈도우를 맞춤화하는 방법을 알아봅니다
Apple은 디지털화를 통해 1984년 데스크탑 경험을 혁신했죠
모노크롬부터
컬러화
Aqua
그 이후로도 macOS 경험의 핵심 역할을 해왔습니다
윈도우는 애플리케이션의 사용자 인터페이스를 그리는 기본 단위입니다
일반적인 윈도우에는 몇 가지 보기 편한 구성 요소가 있습니다
윈도우 상단에는 윈도우 제어기와 제목 도구 막대 항목을 호스팅하는 도구 막대가 있습니다
앱의 주요 콘텐츠는 그 뒤에 놓여 있고 배경은 가장 뒤쪽에 있으며 그림자가 드리워 레이어링과 깊이감을 느낄 수 있습니다
저는 이 시간을 통해 대상 비디오라는 앱에서 윈도우의 이러한 요소를 맞춤화하는 방법을 보여 드릴께요
SwiftUI 앱은 Window와 WindowGroup과 같은 장면으로 구축되어 동영상을 정리하고 재생합니다
이러한 다양한 장면 유형에 대해 더 자세히 알고 싶으시면 ‘SwiftUI 앱에 여러 개의 윈도우 가져오기’와 ‘SwiftUI에서 윈도우 처리하기’를 확인하세요
이제 새로운 SwiftUI API를 사용해 앱의 콘텐츠에 맞게 윈도우를 상세히 조정해 봅니다
기본 윈도우에는 동영상 모음을 이동할 수 있는 기본 인터페이스가 포함되어 있죠
정보 윈도우에는 애플리케이션 버전과 지원 정보가 표시됩니다
동영상 플레이어 윈도우가 있고 미디어 재생도 가능합니다
이러한 각 윈도우를 제공되는 콘텐츠 유형별로 맞춤화하기 위해 변경 사항을 윈도우 도구 막대와 윈도우 동작, 윈도우 배치에 적용하겠습니다
대상 비디오에서 기본 윈도우의 도구 막대를 맞춤화해 보겠습니다
콘텐츠 보기가 있는 WindowGroup에서 생성된 것입니다
현재 윈도우에는 도구 막대와 제목이 표시되어 있습니다
제 디자인은 큰 이미지 아래에 있습니다 이미지를 강조 표시하려면 제목과 도구 막대 배경을 제거하고 이때 .toolbar(removing) 한정자와 .toolbarBackgroundVisibility() 한정자를 사용합니다
이제 큰 이미지가 윈도우의 상단 가장자리까지 확장됩니다
제목이 사용자 인터페이스에서 가려져 보이지 않더라도 여전히 윈도우와 연결되어 있어요 손쉬운 사용과 기타 기능에서 사용될 겁니다
예를 들어 기본 메뉴 항목에는 계속 윈도우 제목이 표시됩니다
몇 줄의 코드만을 추가하여 도구 막대 요소를 디자인에 맞게 맞춤화하여 윈도우 콘텐츠를 강조 표시했어요 다음으로 정보 윈도우의 동작을 재정의합니다
모든 Mac 앱에 정보 윈도우가 있고 기본 메뉴에서 액세스할 수 있어요
여기에는 앱의 버전 번호와 기타 세부 정보가 표시됩니다
대상 비디오에서 정보 윈도우를 맞춤화하여 기본 카탈로그 윈도우의 정갈한 외관과 느낌에 잘 어울리게 설정해 볼께요
시작하기 위해 이전 섹션에 사용한 한정자와 같은 몇 가지 한정자를 추가하여 제목을 숨기고 도구 막대 배경을 제거합니다
저는 .containerBackground() 한정자를 사용하여 윈도우 배경 색상을 소재로 대체하여 윈도우에 약간의 개성을 더합니다 소재는 반투명 유리처럼 부분적으로 투명하기 때문에 데스크탑의 색상이 비쳐 보일 수 있습니다
녹색 줌 윈도우 제어는 비활성화되며 이는 콘텐츠의 고정 크기 때문이죠
정보 윈도우에 정적 정보가 표시되고 항상 기본 메뉴에서 접근할 수 있습니다 노란색 최소화 제어 기능을 비활성화하고 싶습니다
.windowMinimizeBehavior() 한정자를 사용하여 기능을 비활성화합니다
정보 윈도우의 상태 복원 동작을 맞춤화해 보겠습니다
상태 복원은 앱 종료 시 윈도우의 크기와 위치를 저장해요 그러면 다음에 앱이 실행될 때 설정대로 다시 자동으로 열립니다
SwiftUI 앱의 윈도우는 자동으로 복원됩니다 반면 정보 윈도우는 표시되지 않죠 .restorationBehavior() 장면 한정자를 사용해 이 기능을 비활성화합니다
이제 윈도우의 디자인과 동작이 멋지게 맞춤화되었습니다 끝으로, 화면에 표시되는 위치를 정확히 조정해 보겠습니다
동영상 플레이어 윈도우에서 특히 중요한 기능입니다
이상적인 크기는 재생 중인 동영상과 재생하는 화면에 따라 다르며 각각 파란색 실선 테두리와 노란색 점선 테두리로 강조 표시되어 있습니다
동영상은 다양한 크기로 제공되요
일부 동영상은 매우 작아서 화면에 쉽게 맞출 수 있습니다
가로나 세로 혹은 두 방향에서 화면보다 더 큰 동영상도 있으며 동영상이 세로 형식이거나 화면 설정이 그럴 수도 있습니다
재생은 외부 모니터 구성의 수에 영향을 받지 않고 작동해야 합니다
동영상 플레이어 윈도우의 목표는 동영상과 재생되는 화면을 고려해 적절한 위치와 크기를 사용하는 것입니다
가장 먼저 할 작업은 새롭게 생성한 플레이어 윈도우의 첫 배치 위치를 지정하는 것이며 .defaultWindowPlacement 한정자를 사용합니다
이 한정자는 두 개의 매개변수로 클로저를 작업하는데
하나는 콘텐츠의 크기를 쿼리하기 위한 프록시 뷰이고 하나는 디스플레이 정보가 포함된 컨텍스트 값입니다
콘텐츠에서 .sizeThatFits()를 호출해 윈도우의 이상적 크기를 계산하죠 디스플레이에서 visibleRect를 가져와 사용 가능한 영역을 확보하며 메뉴 막대와 도크에서 차지하는 모든 공간을 자동으로 고려합니다
동영상은 기본 크기로 표시되지만 동영상이 화면보다 너무 크면 맞춰서 축소해야 합니다
이 크기로 배치를 반환하고 명시적 위치 지정은 하지 않습니다
기본적으로 윈도우가 가운데에 배치될 것입니다
동영상 플레이어 윈도우가 열려 있는 동안 크기를 조정할 수 있는 다른 방법도 고려해야 합니다
예를 들어 윈도우 메뉴에서 확대/축소를 선택하여 자동으로 윈도우를 확대할 수 있죠 다시 확대/축소를 선택하여
이전 크기로 윈도우를 복원합니다
.windowIdealPlacement 한정자는 확대된 윈도우 크기를 제어합니다
저는 확대된 윈도우가 이상적인 화면 비율을 유지하면서 최대 크기로 설정되도록 합니다
제가 입력한 클로저는 이상적 배치의 클로저와 유사해요 이전과 같이 컨텍스트 값을 사용해 디스플레이 가시 영역을 계산해요
이번에는 윈도우를 디스플레이 크기에 맞춰 확대해요 zoomToFit 헬퍼 함수를 사용하여 구현합니다
몇 가지 변경 사항을 반영하니 동영상 플레이어 윈도우가 콘텐츠, 디스플레이와 더 어울려요
앱 윈도우를 맞춤화하여 이제 각 윈도우가 작업에 맞게 최적화된 느낌입니다
몇 가지 새로운 API가 큰 도움이 될 수 있습니다
macOS Sequoia에서 탐색할 수 있는 윈도우 맞춤화가 더 많이 있어요
가령 일반 윈도우 스타일을 사용해 테두리 없는 윈도우를 설정하거나
조건부로 시작 시 처음 보여지는 환영 윈도우처럼 나만의 경험을 만들 수 있습니다
몇 가지 가능한 예시에 불과하므로 이러한 맞춤화가 프로젝트에 영감을 줄 수 있기를 바랍니다
정리하면 도구 막대에 스타일을 적용하여 윈도우 콘텐츠, 목적을 보완하세요
윈도우 동작을 앱 윈도우의 기능과 일치하도록 재구성합니다
윈도우 배치를 세부적으로 조정해 모든 디스플레이 구성 전반에서 효과적인 경험을 누리세요 SwiftUI 관련 자료를 확인하고 새로운 API로 실험하여 디자인 목표에 반영하세요
시청해 주셔서 감사합니다 테두리가 없는 동영상 윈도우에서 저를 보고 계신지 궁금하네요!
-
-
3:11 - Style Toolbars - Removing Title
.toolbar(removing: title)
-
3:14 - Style Toolbars - Removing Toolbar Background
.toolbarBackgroundVisibility(.hidden, for: .windowToolbar)
-
4:33 - Refine Behaviors - Adding Container Background
.containerBackground(.thickMaterial, for: .window)
-
5:13 - Refine Behaviors - Minimize Behavior
.windowMinimizeBehavior(.disabled)
-
5:44 - Refine Behaviors - Restoration Behavior
.restorationBehavior(.disabled)
-
7:11 - Adjust Placement - Default Placement
.defaultWindowPlacement { content, context in var size = content.sizeThatFits(.unspecified) let displayBounds = context.defaultDisplay.visibleRect // modify size based on display bounds return WindowPlacement(size: size) }
-
8:35 - Adjust Placement - Ideal Placement
.windowIdealPlacement { content, context in var size = content.sizeThatFits(.unspecified) let displayBounds = context.defaultDisplay.visibleRect // modify size based on display bounds return WindowPlacement(size: size) }
-
9:48 - Borderless Window
.windowStyle(.plain)
-
9:53 - Default Launch Behavior
.defaultLaunchBehavior(.presented)
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.