보기 상태 변경을 통한 최상의 픽셀 활용법

Windows 8은 다양한 화면 크기와 보기 상태에서 앱을 사용할 수 있도록 지원합니다. 사용자는 25인치 데스크톱 모니터 한쪽에서 앱을 사용하거나 10인치 와이드스크린 태블릿의 전체 화면에서 사용할 수 있습니다. 이에 따라, 개발자들도 이러한 각각의 화면 크기와 보기 상태에 최적화된 앱을 개발하고자 할 것입니다. 이 글은 앱의 현재 크기와 보기 상태를 코드에서 추적하는 방법을 설명합니다. 또한 Windows 8 Consumer Preview에서 앱을 작성할 때 화면 크기와 보기 상태를 변경할 수 있는 방법도 소개합니다.

우리는 //build/에서 다양한 화면 시나리오에 맞게 앱을 설계할 수 있는 몇 가지 방법을 소개했습니다. 이에 대한 예제는 XAML 강연 또는 HTML 강연을 참조하십시오. 최근에 Windows 8 빌드 블로그에도 화면 배율 조정에 대한 연구 및 설계 관련 내용을 공유했습니다. 일반 마크업을 사용하면 명시적으로 코드를 쓰지 않아도 화면 크기 변경을 조정할 수 있습니다. 하지만 앱이 어떤 보기 상태에 있는지 즉, 앱이 세로, 전체 화면, 채워짐 또는 사이드 모드인지 여부를 추적하고 이에 따라 반응하도록 코드를 작성해야 할 경우가 있습니다. 예를 들어 이 그림에서와 같이 HTML ListView를 사용하여 항목을 표시하고 있는 경우 전체 화면 모드에서 GridLayout을 사용하고 사이드 모드에서 ListLayout을 사용하고자 할 수 있습니다. XAML에서 비슷한 방법으로 GridView 컨트롤과 ListView 컨트롤 간을 전환하고자 할 수 있습니다. 이 작업을 어떻게 수행하는지를 알아보기 위해서 코드에서 크기 조정 및 보기 상태 변경을 확인하는 방법을 살펴보겠습니다.

타일 3개씩 3행으로 그리드에 배열된 날씨 앱의 전체 보기 상태, 오른쪽의 사이드 보기 화면에는 동일한 타일이 1열로 배열되어 있음

왼쪽의 전체 보기 상태 화면에는 그리드 레이아웃(HTML) 또는 GridView 컨트롤(XAML)이 있는 반면
오른쪽의 사이드 보기 상태 화면에는 목록 레이아웃(HTML) 또는 ListView 컨트롤(XAML)이 있습니다.

크기 조정 및 보기 상태 변경의 기본

화면 크기 조정 및 보기 상태 변경의 기본 패턴은 XAML 및 HTML로 작성된 Windows 8 앱에서 동일합니다. 콜백 함수를 각 프레임워크에서 제공하는 적절한 이벤트에 연결하고 추가적으로 필요한 정보를 쿼리하면 됩니다.

예를 들어 다음 코드 예제에서와 같이 JavaScript에서는 기본 창 크기 조정 이벤트에 대한 처리기를 만들 수 있으며 이는 간단한 콜백 함수입니다. 이 이벤트를 사용하여 앱의 표시 영역의 크기가 언제 조정되었는지를 확인하고 이 앱 영역에 맞는 새로운 크기를 찾을 수 있습니다.

JavaScript

 function handleResize(eventArgs) {
    var appWidth = eventArgs.view.outerWidth;
    var appHeight = eventArgs.view.outerHeight;
    ...
}

window.addEventListener("resize", handleResize);

이와 비슷하게 XAML에서는 이벤트 처리기를 설정하기 위해 현재 창에 SizeChanged 이벤트를 사용할 수 있습니다.

C#

 private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    double AppWidth = e.Size.Width;
    double AppHeight = e.Size.Height;
}

Window.Current.SizeChanged += OnWindowSizeChanged;

Windows 8 앱을 프로그래밍할 때 WinRT를 사용하여 현재 보기 상태를 직접 쿼리할 수도 있습니다. WinRT는 앱의 현재 보기 상태를 알려 주는 열거 값을 제공합니다.

JavaScript

 var currentViewState = Windows.UI.ViewManagement.ApplicationView.value;

C#

var

  CurrentViewState = Windows.UI.ViewManagement.ApplicationView.Value;

JavaScript로 작성된 Windows 8 앱은 msMatchMedia 함수도 지원합니다. 이 함수는 DOM 창 개체를 통해 작동되며 전체 화면 가로와 1600픽셀 너비 화면을 조합하는 경우와 같이 여러 미디어 쿼리를 사용하는 조건이 있는 경우 유용할 수 있습니다.

JavaScript

 var isSnapped = window.msMatchMedia(“(-ms-view-state:fullscreen-landscape) and 
(min-width: 1600px”).matches;

JavaScript

 function handleSnappedMode(mql) {
if (mql.matches) {
        ...
        }
}
window.msMatchMedia(“(-ms-view-state:fullscreen-landscape) and (min-width: 
1600px”).addListener(handleSnappedMode);

Consumer Preview의 크기 조정 및 보기 상태

보기 상태 및 화면 크기 정보에 액세스하는 기본 방법에 대해 알아보았으니 이제 화면 크기 조정을 처리하기 위해 이 기능을 배포하는 방법을 설명하겠습니다. Windows 8 Consumer Preview에서 크기 조정 이벤트와 보기 상태 변경 이벤트의 순서는 결정되어 있기 때문에 보기 상태 이벤트(및 연결된 콜백 함수)는 항상 크기 조정 이벤트보다 먼저 발생합니다. 이런 점 때문에 현재 보기 상태에 액세스하려면 항상 크기 조정 이벤트가 실행되기를 기다려야 합니다. 이렇게 하면 코드에서 크기 및 보기 상태를 간편하면서도 일관성 있게 변경할 수 있습니다. 크기 조정 이벤트가 실행되고 동반하는 콜백 함수가 작동될 때까지 기다리면 현재 표시 영역 및 보기 상태에 대해 반환된 정보가 동기화됨을 확인할 수 있습니다.

레이아웃 변경을 처리하는 코드를 트리거하는 데 크기 조정 이벤트를 사용하는 것도 좋습니다. 왜냐하면 보기 상태에서 변경이 발생되지 않는 일부 화면 크기 조정 이벤트(예: 모니터 해상도 변경 또는 PC 원격 연결)가 있기 때문입니다. 또한, 레이아웃 변경을 처리하는 코드를 한곳에 모아 놓는 것은 다른 화면 변경 이벤트에 다른 코드가 작동되도록 하는 것보다 좋은 프로그래밍 관행입니다.

예를 들어 한 개발자가 현재 화면 해상도에 최적화된 다른 크기의 배경화면 이미지를 다운로드하는 앱을 작성하기를 원한다고 가정해 봅시다. 그는 사이드 모드에서는 배경화면의 타일에 작은 이미지를 다운로드하고, 채워짐 모드에서는 표준 4:3 가로 세로 비율 이미지를, 전체 화면-가로 모드에서는 16:9 가로 세로 비율 이미지를 다운로드할 수 있도록 하려고 합니다. 또한 화면 높이에 따라 각 가로 세로 비율에 맞는 다른 이미지 해상도를 선택할 수 있게 만들기를 원합니다.

이러한 지침에 맞게 우리는 다음과 같이 크기 조정 이벤트를 기준으로 한 콜백 함수를 설정하고 이 콜백 함수 내에 WinRT API를 사용하여 현재 보기 상태를 쿼리합니다.

JavaScript

 function handleResize(eventArgs) {
    var currentViewState = Windows.UI.ViewManagement.ApplicationView.value;
    var appHeight = eventArgs.view.outerHeight;
    var appWidth = eventArgs.view.outerWidth;

    // downloadImage requires accurate view state and app size!
    downloadImage(currentViewState, appHeight, appWidth);
}

window.addEventListener("resize", handleResize);

 

C#

 private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
 var CurrentViewState = Windows.UI.ViewManagement.ApplicationView.Value;
 double AppWidth = e.Size.Width;
 double AppHeight = e.Size.Height;

    // DownloadImage requires accurate view state and app size!
    DownloadImage(CurrentViewState, AppHeight, AppWidth);
}

Window.Current.SizeChanged += OnWindowSizeChanged;

반대로 보기 상태 변경에서 트리거하는 콜백 함수에서 앱 표시 영역 크기를 쿼리하려고 했다면 올바른 보기 상태 정보를 얻을 수는 있지만 앱 표시 영역 크기는 업데이트되지 않았을 것입니다. 따라서 이러한 상황에서 사이드 모드에서 전체 화면-가로 보기로 앱이 전환되면 AppWidth는 320픽셀이 되고 보기 상태는 전체 화면-가로가 됩니다. 이러한 값을 DownLoadImage로 전달하면 잘못된 이미지 크기를 다운로드하게 됩니다.

크기 조정 이벤트에서 트리거한 콜백을 사용하는 이 지침은 다른 시나리오에도 적용됩니다. 예를 들어 JavaScript에서 ListView 컨트롤 레이아웃을 보기 상태에 따라 그리드에서 목록으로 변경하면 보기 상태가 변경되는 경우 콜백이 발생하도록 설정할 수 있습니다. 하지만 화면 크기가 조정되기 전에 ListView 레이아웃을 설정하면 ListView 컨트롤에 두 개의 레이아웃 단계를 전달하게 됩니다. 즉, 화면 크기 조정되기 전에 하나, 크기가 조정된 후에 하나가 전달됩니다. WinJS ListView 컨트롤은 크기 조정 이벤트를 자동으로 처리하지만 보기 상태 변경 이벤트를 처리하지 않습니다. 앞서 보았던 DownloadImage 예제와는 다르게 사용자가 차이를 직접 확인할 수 없지만 앱에서 레이아웃을 설정하는 데 더 많은 시간이 걸리기 때문에 반응 속도가 현저하게 느려집니다. 따라서 이에 따라 현재 보기 상태를 쿼리하고 ListView 레이아웃을 설정하기 전에 화면 크기 조정에 따른 콜백을 기다리는 편이 좋습니다.

JavaScript

 function handleResize(eventArgs) {
    var isSnapped = (Windows.UI.ViewManagement.ApplicationView.value === 
Windows.UI.ViewManagement.ApplicationViewState.snapped);
    listView.layout = isSnapped ? new WinJS.UI.ListLayout() : new WinJS.UI.GridLayout();
}

window.addEventListener("resize", handleResize);

XAML에서 다른 상태 간을 전환하려면 VisualStateManager(VSM) API를 사용하여 개별 보기에 표시해야 하는 XAML 요소를 정의합니다. Visual Studio 2011 Beta 도구를 사용 중인 경우 그리드 앱 템플릿용 프로젝트 템플릿에 정의된 이러한 API 예제를 확인할 수 있습니다.

XAML

 <VisualStateManager.VisualStateGroups>
    <!-- Visual states reflect the application's view state -->
    <VisualStateGroup>
        <VisualState x:Name="FullScreenLandscape"/>
        <VisualState x:Name="Filled"/>

        <!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
        <VisualState x:Name="FullScreenPortrait">
            <!-- definition of what UI elements should display or change would go here in Storyboard 
elements -->
        </VisualState>

        <!-- The back button and title have different styles when snapped, and the list representation 
is substituted for the grid displayed in all other view states -->
        <VisualState x:Name="Snapped">
            <!-- definition of what UI elements should display or change would go here in Storyboard 
elements -->
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

다른 보기 상태에 정의된 VisualState 그룹을 확인하십시오. 그러면 SizeChanged 이벤트에서 상태가 변경될 때 코드에서 이를 변경할 수 있습니다.

C#

 private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
 // get the view state after the size has changed
 string CurrentViewState = Windows.UI.ViewManagement.ApplicationView.Value.ToString();
 
 // using VisualStateManager make sure we navigate to the correct state definition
    VisualStateManager.GoToState(this, CurrentViewState, false);
}

이 예제에서 확인한 바와 같이 SizeChangedApplicationView API가 조합된 VSM을 사용하면 화면 레이아웃 변경을 조정할 수 있는 유연한 메커니즘이 제공됩니다.

결론

이 글에서는 화면 크기 조정 이벤트와 보기 상태 변경을 코드에서 확인할 수 있는 방법을 살펴보았습니다. Consumer Preview의 경우 제가 여기에서 수행했던 것과 같이 보기 상태 정보에 대해 WinRT를 쿼리하기 전에 화면 크기 이벤트 변경을 확인하는 것이 좋습니다. 이 지침을 따르는 경우 앱이 크기 조정될 때마다 코드가 올바른 현재 화면 크기 및 보기 상태 정보를 확인하게 됩니다. 더 많은 예제를 보려면 Windows 8 SDK 샘플을 살펴보십시오. 이 주제에 대한 여러분의 생각과 의견을 많이 들을 수 있기를 바랍니다.

- Windows 프로그램 관리자, Chris Jones

이 블로그 글을 작성하는 데 도움을 준 Tim Heuer에게 특히 감사드립니다.